shiro+jwt踩坑实录
比较乱,没啥条理,主要是记录自己踩过的一些坑
shiroConfig
1.首先配置shiroFilter
shiroFilter配置
1.1配置securityManager
securityManager是shiro相对核心。
1.1.1 配置Authenticator
首先配置setAuthenticator,由于我们要使用password和token两种登陆方式,所以需要使用MultiRealmAuthenticator,多领域校验;
MultiRealmAuthenticator
----Authenticator配置参数setAuthenticationStrategy,主要有三个选项,
--------1.FirstSuccessfulStrategy 第一个realm通过则为校验通过。
--------2.AtLeastOneSuccessfulStrategy,任意一个realm通过则为校验通过。
--------3.AllSuccessfulStrategy,全部realm通过则为校验通过。
1.1.2 配置Realm
然后需要配置setRealm(多realm需setRealms,参数为List),
(这边是一个坑,authenticator和realm是有顺序的,必须先setAuthenticator,再setRealms,不然realm不起作用,还会抛出java.lang.IllegalStateException: Configuration error: No realms have been configured! One or more realms must be present to execute an authorization operation.)。
passwordRealm(自定义Realm,继承AuthorizingRealm)
PasswordRealm passwordRealm = new UserRealm();
passwordRealm .setName("userRealm"); //
passwordRealm .setCredentialsMatcher(agentCredentialsMatcher());//匹配器
passwordRealm .setCacheManager(redisCacheManager());//缓存管理,这里使用redis
passwordRealm .setCachingEnabled(true);//是否开启缓存
passwordRealm .setAuthenticationCachingEnabled(false);//是否缓存身份验证信息
passwordRealm .setAuthenticationCacheName("aaa");//存放身份缓存的key
passwordRealm .setAuthorizationCachingEnabled(true);//是否缓存权限信息
passwordRealm .setAuthorizationCacheName("bbb");//存放缓存权限的key
jwtRealm(自定义realm,继承AuthorizingRealm)
JwtRealm jwtRealm = new JwtRealm();
jwtRealm.setName("jwtRealm");
jwtRealm.setCredentialsMatcher(jwtCredentialsMatcher());
jwtRealm 需重写 supports
// 限定这个Realm只支持我们自定义的JWT Token
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
1.1.3 关闭shiro的session
然后在securityManager关闭shiro的session
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
manager.setSubjectDAO(subjectDAO);
1.2 配置filters
这边我们配置一个JwtFilter,用于拦截请求校验。
Map<String, Filter> filters = new LinkedHashMap<>();//这边使用LinkenHashMap,因为filter是有序的
filters.put("authc",new JwtFilter());//authc校验,配置使用jwtFilter,
(这边有个坑,这个需要使用new,不能使用spring管理,使用spring管理会使所有的请求都通过这个filter,导致不需校验的anon请求也被校验,具体原因未知,还需查询shiro源码)
1.2.1 JwtFiter
JwtFilter,继承自AuthenticatingFilter
需重写createToken方法,
protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {
String jwtToken = getRequestToken((HttpServletRequest) servletRequest);
return new JwtToken(jwtToken);
}
这里需要使用我们自定义token,这个token对应shiro的token,非jwt的token。
这个方法作用是在使用shiro的subject.login()的时候,只用jwtToken,并使用对应的realm校验。
1.2.1.1 JwtToken
JwtToken,需要实现AuthenticationToken,
主要属性为 private String token,这个对用jwt生成的token
先写到这吧