SpringSecurity+jwt自定义认证每次都需要认证的问题
1、先说出现的问题:
项目需要app自定义登录认证,按照SpringSecurity默认的用户名和密码认证方式自定义了token,provider,UserService,UserDetails;登录成功返回token后,app拿着token去访问后台资源时,一直提示403未认证,调试代码发现,每次访问都要走provider的authcatication方法去数据库认证;按理说jwtfilter校验token通过后就不需要再次去数据库查用户了,但是现在是每次都要去查一次,这个时候jwt设置的token中是没有密码的,当provider去验证的时候发现没有密码就报403认证失败(认证过后,再次拿token去访问资源是不应该去数据库认证的);
2、解决问题:
通过断点发现,SpringSecurity的认证拦截器中有个方法调用的是Authentication接口的isAuthentication方法,这个方法如果返回的是true,就不去provider中认证了,而这个方法就是在AbstractAuthenticationToken 中定义,这个时候我们看一下自定义的Authentication
public class AppAuthenticationToken extends AbstractAuthenticationToken { private final Object principal; private Object credentials; public AppAuthenticationToken( Object principal, Object credentials,Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; this.credentials = credentials; super.setAuthenticated(true); // must use super, as we override } public AppAuthenticationToken(Object principal, Object credentials) { super(null); this.principal = principal; this.credentials = credentials; setAuthenticated(false); } public Object getCredentials() { return this.credentials; } public Object getPrincipal() { return this.principal; } public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { if (isAuthenticated) { throw new IllegalArgumentException( "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); } super.setAuthenticated(false); } @Override public void eraseCredentials() { super.eraseCredentials(); credentials = null; } }
看到上面的构造方法中都有setAuthenticated这个方法,这个方法就是给Authentication接口的isAuthentication方法提供参数的;我们只要在jwtfilter中验证通过了token,就要调用AppAuthenticationToken( Object principal, Object credentials,Collection<? extends GrantedAuthority> authorities)这个构造,告诉SpringScurity认证拦截器,我已经在jwtfilter中校验过了,你不需要检验。这样就ok了。