springBoot整合shiro
自定义Realm域
public class MyRealm extends AuthorizingRealm {
public void setName(String name){
super.setName("customRealm");
}
@Resource
private UserService userService;
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取用户名
String username = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 给该用户设置角色,角色信息存在t_role表中取
Set<String> roles = userService.getRoles(username);
authorizationInfo.setRoles(userService.getRoles(username));
// 给该用户设置权限,权限信息存在t_permission表中取
Set<String> permissions = userService.getPermissions(username);
authorizationInfo.setStringPermissions(userService.getPermissions(username));
return authorizationInfo;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 根据token获取用户名
String username = (String) authenticationToken.getPrincipal();
// 根据用户名从数据库中查询该用户
User user = userService.getByUsername(username);
if(user != null) {
// 把当前用户存到session中
SecurityUtils.getSubject().getSession();
SecurityUtils.getSubject().getSession().setAttribute("user", user);
// 传入用户名和密码进行身份认证,并返回认证信息
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "myRealm");
return authcInfo;
} else {
return null;
}
}
}
Shiro 配置
接下来需要对 Shiro 进行配置。我们主要配置三个东西:自定义 realm、安
全管理器 SecurityManager 和 Shiro 过滤器。如下:
@Configuration
public class ShiroConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
//1.创建realm,交给spring容器管理
@Bean
public MyRealm getRealm(){
return new MyRealm();
}
/**
* 注入安全管理器
* @return SecurityManager
*/
@Bean
public SecurityManager securityManager(MyRealm myRealm) {
// 将自定义realm加进来
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myRealm);
//将自定义的回话管理器注册到安全管理器中
securityManager.setSessionManager(sessionManager());
//将自定义的redis缓存管理器注册到安全管理器
securityManager.setCacheManager(cacheManager());
return securityManager;
}
/**
* 注入Shiro过滤器
* @param securityManager 配置安全管理器
* @return ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
// 定义shiroFactoryBean
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
// 设置自定义的securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 设置默认登录的url,身份认证失败会访问该url
shiroFilterFactoryBean.setLoginUrl("/login");
// 设置成功之后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/success");
// 设置未授权界面,权限认证失败会访问该url
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
// LinkedHashMap是有序的,进行顺序拦截器配置
Map<String,String> filterChainMap = new LinkedHashMap<>();
// 配置可以匿名访问的地址,可以根据实际情况自己添加,放行一些静态资源等
filterChainMap.put("/css/**", "anon");
filterChainMap.put("/imgs/**", "anon");
filterChainMap.put("/js/**", "anon");
filterChainMap.put("/swagger-*/**", "anon");
filterChainMap.put("/swagger-ui.html/**", "anon");
// 登录url 放行
filterChainMap.put("/login", "anon");
// “/user/admin” 开头的需要身份认证
filterChainMap.put("/user/admin*", "authc");
// “/user/student” 开头的需要角色认证,是“admin”才允许
filterChainMap.put("/user/student*/**", "roles[admin]");
// “/user/teacher” 开头的需要权限认证,是“user:create”才允许
filterChainMap.put("/user/teacher*/**", "perms[\"user:create\"]");
// filterChainMap.put("/user/test*/**", "perms[\"student:create\"]");
// 配置logout过滤器
filterChainMap.put("/logout", "logout");
// 所有url必须通过认证才可以访问,这行代码必须放在所有权限设置的最后
// filterChainMap.put("/**", "authc");
// 设置shiroFilterFactoryBean的FilterChainDefinitionMap
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
return shiroFilterFactoryBean;
}
//4.开启对shiro注解的支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
*1.redis 的控制器,操作redis
*/
public RedisManager redisManager(){
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
return redisManager;
}
/**
*2.sessionDao
*/
public RedisSessionDAO redisSessionDAO(){
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
/**
*3.回话管理器
*/
public DefaultWebSessionManager sessionManager(){
CustomSessionManager sessionManager = new CustomSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
sessionManager.setCacheManager(cacheManager());
return sessionManager;
}
/**
*4.缓存管理器
*/
public RedisCacheManager cacheManager(){
RedisCacheManager cacheManager = new RedisCacheManager();
cacheManager.setRedisManager(redisManager());
return cacheManager;
}
}
自定义的自定义的sessionManager
public class CustomSessionManager extends DefaultWebSessionManager {
/**
*
*
* 指定sessionId获取方式
*
* 头信息中具有sessionId
* 请求头:Authorization : session
* String id = WebUtils.toHttp(request).getHeader("Authorization");
* @param request
* @param response
* @return
*/
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//获取请求头Authorization中的数据
String id = WebUtils.toHttp(request).getHeader("Authorization");
if (StringUtils.isEmpty(id)){
//如果没有携带,可以生成新的sessionId
// String id1 = UUID.randomUUID().toString().replace("-", "");
return super.getSessionId(request,response);
}else {
//返回sessionId
//来源 请求头
//sessionId是什么
//sessionId要不还要验证
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
}
}
}