Spring Security开发调试记录详解编程语言

Spring Security+jwt开发调试记录

首先需要在工程的websecurityconfig文件中添加这样一个注解

由于问题出在密码正确却无法登录,因此从认证方面找原因,选择在attemptAuthentication函数中设置断点在这里插入图片描述
可以看到拦截器顺利的获取到了来自于前端的信息,这至少证明,来自于前端的信息是没有问题的,接着往下走。
在这一行stepinto
在这里插入图片描述
这句话的意思是获取当前的一个authenticationManager变量并调用其中的authenticate()函数,查看一下authenticationManager变量的具体数据
在这里插入图片描述
再看一下authenticate()函数的具体实现
在这里插入图片描述
进去之后才发现是一个接口,查看一下他的具体实现,
在这里插入图片描述
这里我们要看的是security目录下的内容,进入ProviderManager查看实现

public Authentication authenticate(Authentication authentication) 
throws AuthenticationException {
 
Class<? extends Authentication> toTest = authentication.getClass(); 
AuthenticationException lastException = null; 
AuthenticationException parentException = null; 
Authentication result = null; 
Authentication parentResult = null; 
boolean debug = logger.isDebugEnabled(); 
for (AuthenticationProvider provider : getProviders()) {
 
if (!provider.supports(toTest)) {
 
continue; 
} 
if (debug) {
 
logger.debug("Authentication attempt using " 
+ provider.getClass().getName()); 
} 
try {
 
result = provider.authenticate(authentication); 
if (result != null) {
 
copyDetails(authentication, result); 
break; 
} 
} 
catch (AccountStatusException | InternalAuthenticationServiceException e) {
 
prepareException(e, authentication); 
// SEC-546: Avoid polling additional providers if auth failure is due to 
// invalid account status 
throw e; 
} catch (AuthenticationException e) {
 
lastException = e; 
} 
} 
if (result == null && parent != null) {
 
// Allow the parent to try. 
try {
 
result = parentResult = parent.authenticate(authentication); 
} 
catch (ProviderNotFoundException e) {
 
// ignore as we will throw below if no other exception occurred prior to 
// calling parent and the parent 
// may throw ProviderNotFound even though a provider in the child already 
// handled the request 
} 
catch (AuthenticationException e) {
 
lastException = parentException = e; 
} 
} 
if (result != null) {
 
if (eraseCredentialsAfterAuthentication 
&& (result instanceof CredentialsContainer)) {
 
// Authentication is complete. Remove credentials and other secret data 
// from authentication 
((CredentialsContainer) result).eraseCredentials(); 
} 
// If the parent AuthenticationManager was attempted and successful than it will publish an AuthenticationSuccessEvent 
// This check prevents a duplicate AuthenticationSuccessEvent if the parent AuthenticationManager already published it 
if (parentResult == null) {
 
eventPublisher.publishAuthenticationSuccess(result); 
} 
return result; 
} 
// Parent was null, or didn't authenticate (or throw an exception). 
if (lastException == null) {
 
lastException = new ProviderNotFoundException(messages.getMessage( 
"ProviderManager.providerNotFound", 
new Object[] {
 toTest.getName() }, 
"No AuthenticationProvider found for {0}")); 
} 
// If the parent AuthenticationManager was attempted and failed than it will publish an AbstractAuthenticationFailureEvent 
// This check prevents a duplicate AbstractAuthenticationFailureEvent if the parent AuthenticationManager already published it 
if (parentException == null) {
 
prepareException(lastException, authentication); 
} 
throw lastException; 
} 

从源码中我们可以看到providers是非常重要的一个成员变量,这个函数通过遍历列表里的一个个provider,判断它是否支持参数authentication的认证,这里我们就可以回去看一下authenticationManager变量的的providers究竟有哪些,
在这里插入图片描述
里面只有一项内容查阅该类的相关资料,可知这个类并不指出usernamepassword形式的authentication
难道是这里出错了?
阅读完代码后继续运行
在这里插入图片描述
这一步在意料之中,接着往下运行
在这里插入图片描述
原来除了判断自身的provider之外还需要调用parent元素中的authenticate()函数,查看parent里面的provider
在这里插入图片描述
可以看到parent里面的provider是可以支持认证的
接着运行可以看到调用了provider的authenticate()函数
在这里插入图片描述
在这里插入图片描述
继续stepinto查看user是如何获得的。
在这里插入图片描述
看到了获取Userdetail的函数loadUserByUsername
在这里插入图片描述
就是在这里出了问题,本来这个函数应该调用我自己书写的UserDetailsServiceImp结果却去到了另一个实现类,我判断是因为我的UserDetailsServiceImp没有被识别于是会去检查了一下代码,[email protected]
加上去之后问题解决
在这里插入图片描述

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/17791.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论