-
缓存使用redis,自定义ShiroRedisCache、ShiroRedisCacheManager用于存储用户缓存信息
-
自定义MyShiroToken继承自AuthenticationToken。用于用户名密码载体进行认证
public class MyShiroToken implements AuthenticationToken {
private AdminUser adminUser;
public MyShiroToken(AdminUser adminUser) {
this.adminUser = adminUser;
}
@Override
public Object getPrincipal() {
return adminUser.getAccount();
}
@Override
public Object getCredentials() {
return adminUser.getPswd();
}
}
- MyShiroRealm用户用户登录验证,及权限校验
public class MyShiroRealm extends AuthorizingRealm {
/**
* 用以支持自定义token
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof MyShiroToken;
}
/**
* 获取用户权限信息
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//加载用户角色权限信息
authorizationInfo.addRole(adminRole.getName());
authorizationInfo.addStringPermission(perm);
return authorizationInfo;
}
/**
* 验证用户登录信息
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
MyShiroToken adminUserToken = (MyShiroToken) token;
//查询用户信息
AdminUser adminUser;
if (null == adminUser) {
throw new CommonException("用户不存在");
}
return new SimpleAuthenticationInfo(adminUserToken.getPrincipal(), adminUserToken.getCredentials(), getName());
}
}
}
}
- 自定义登录、权限filter。用户返回json错误信息
- shiro配置信息
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, Filter> filterMap = Maps.newHashMap();
filterMap.put("myShiroLoginFilter", new MyShiroLoginFilter());
shiroFilterFactoryBean.setFilters(filterMap);
//拦截器
Map<String, String> filterChainDefinitionMap = Maps.newHashMap();
//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
// roles[管理员]
//
// -->
filterChainDefinitionMap.put("/login", "anon");
//加载系统权限
loadPermsUrl(filterChainDefinitionMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public MyShiroRealm myShiroRealm() {
return new MyShiroRealm();
}
/**
* 生成DefaultWebSecurityManager bean,并设置我们自定义的Realm
*
* @return
*/
@Bean
public DefaultWebSecurityManager securityManager(RedisTemplate<Object, Object> template) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 配置 rememberMeCookie 查看源码可以知道,这里的rememberMeManager就仅仅是一个赋值,所以先执行
securityManager.setRememberMeManager(rememberMeManager());
// 配置 缓存管理类 cacheManager,这个cacheManager必须要在前面执行,因为setRealm 和 setSessionManage都有方法初始化了cachemanager,看下源码就知道了
securityManager.setCacheManager(cacheManager(template));
securityManager.setRealm(myShiroRealm());
// 配置 sessionManager
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* cookie管理对象
*
* @return CookieRememberMeManager
*/
private CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
// rememberMe cookie 加密的密钥
cookieRememberMeManager.setCipherKey(Base64.decode("test"));
return cookieRememberMeManager;
}
/**
* rememberMe cookie 效果是重开浏览器后无需重新登录
*
* @return SimpleCookie
*/
private SimpleCookie rememberMeCookie() {
// 这里的Cookie的默认名称是 CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME
SimpleCookie cookie = new SimpleCookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME);
// 是否只在https情况下传输
cookie.setSecure(false);
// 设置 cookie 的过期时间,单位为秒,这里为一天
cookie.setMaxAge(24 * 3600);
return cookie;
}
/**
* session 管理对象
*
* @return DefaultWebSessionManager
*/
private DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// 设置session超时时间,单位为毫秒
sessionManager.setGlobalSessionTimeout(30 * 60 * 1000);
sessionManager.setSessionIdCookie(new SimpleCookie("session-id"));
// 网上各种说要自定义sessionDAO 其实完全不必要,shiro自己就自定义了一个,可以直接使用,还有其他的DAO,自行查看源码即可
sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
return sessionManager;
}
private ShiroRedisCacheManager cacheManager(RedisTemplate template) {
return new ShiroRedisCacheManager(template);
}
}
参考:
1,https://shiro.apache.org/spring-boot.html
2,https://segmentfault.com/a/1190000013875092
3,https://pushy.site/2018/11/21/spring-shiro/
4,https://blog.youkuaiyun.com/u013615903/article/details/78781166
5,https://www.cnblogs.com/yfzhou/p/9813177.html