做毕设的时候遇到的禁用session 各种报错 ,所以记录一下
很多篇同样的文章 都说这个一加上就报错,但是这个工厂是必须要加入的 在源码里面有说到 debug就看到了
StatelessDefaultSubjectFactory.java
public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {
@Override
public Subject createSubject(SubjectContext context) {
//不创建session
context.setSessionCreationEnabled(false);
return super.createSubject(context);
}
}
ShiroConfig.java
securityManager.setSubjectFactory(new StatelessDefaultSubjectFactory());
无状态shiro报DisabledSessionException
ShiroConfig.java中 有一个坑
authc 必须认证 / 默认拦截器authc,源码中有去调用getSession()方法的,但这个时候我们又不创建session,这时就报错。所以要自己去定义一个Filter();
在创建初 如果用自己写的realm的话 比较的流程是 通过加密两个不同的realm 得到一个hash值,密码比较器 doCredentialsMatch… 就会去取这两个Realm 的 SimpleAuthenticationInfo() (该方法加密后得到的是Hash) 根据两个hash 进行equals比较
AuthenticatingRealm.java 主要调用
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
CredentialsMatcher cm = this.getCredentialsMatcher();
if (cm != null) {
if (!cm.doCredentialsMatch(token, info)) {
String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
throw new IncorrectCredentialsException(msg);
}
} else {
throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify credentials during authentication. If you do not wish for credentials to be examined, you can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
}
}
其中
!cm.doCredentialsMatch(token, info)
会去调用 JwtCredentialsMatcher,一定要注意 在JwtCredentialsMatcher是否返回true
最主要的密码认证器
HashedCredentialsMatcher.java
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenHashedCredentials = this.hashProvidedCredentials(token, info);
Object accountCredentials = this.getCredentials(info);
return this.equals(tokenHashedCredentials, accountCredentials);
}
tokenHashedCredentials 来源于你输入的账号(JwtToken.getCredentials())
accountCredentials 来源于你
还有一个细节点在于
public class JwtToken implements AuthenticationToken {
...
@Override
public Object getCredentials() {
// 注意 重写这个方法中 需要return 的是密码!!!!
// 很多博客中都是返回token 或者返回一个user对象,但实则不是
return JWTUtils.verify(token).getClaim("userPassword").asString().toCharArray();
}
...
}
至于 为什么密码要toCharArray (网上给出的回答)