springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
2021-06-30 17:07
标签:type roc iter utc 数据库 release intercept ns3 path 相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群redis版)整合教程 参考此教程前请先阅读 2.springboot+shiro+redis(单机redis版)整合教程,此教程是在其基础上进行修改添加动态角色权限的。 本教程整合环境: java8 maven redis(单机) 开发工具: idea 版本: springboot 1.5.15.RELEASE 注: 1.本教程数据操作是模拟数据库操作,并没有真正进行持久化,自行修改即可。 项目结构,在 springboot+shiro+redis(单机redis版)整合教程 基础上进行的添加和修改结构如下: 首先添加角色权限实体类RolesPermissions.java 添加service层 RolesPermissionsService.java和 RolesPermissionsServiceImpl.java RolesPermissionsService.java: RolesPermissionsServiceImpl.java: 修改登录相关接口 UserController.java: 修改授权相关 UserShiroRealm.java: 自定义角色权限校验器roleOrFilter(注:默认的roles为and关系,由于实际项目需要更多为或者关系,故自定义此类) CustomRolesAuthorizationFilter.java: 使用自定义的角色权限校验器roleOrFilter,ShiroPermissionFactory.java: shiro配置类ShiroConfig.java修改如下: 角色权限刷新器FilterChainDefinitions.java: 角色权限刷新器FilterChainDefinitions.java的使用示例TestController.java: 然后启动项目,RolesPermissionsServiceImpl.java类中的获取数据库(模拟)中所有角色权限和获取用户角色权限可自行修改测试。实际应用于项目也只需要修改这个类为查询实际数据库数据即可。 springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制) 标签:type roc iter utc 数据库 release intercept ns3 path 原文地址:https://www.cnblogs.com/007sx/p/9640685.htmlpackage webapp.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class RolesPermissions implements Serializable {
private static final long serialVersionUID = 1L;
/**
* @备注:
* @字段:id BIGINT(19)
*/
private Long id;
/**
* @备注:创建时间
* @字段:create_time DATETIME(19)
*/
private java.util.Date createTime;
/**
* @备注:更新时间
* @字段:update_time DATETIME(19)
*/
private java.util.Date updateTime;
/**
* @备注:角色id
* @字段:roles_id BIGINT(19)
*/
private Long rolesId;
/**
* @备注:权限id
* @字段:permissions_id BIGINT(19)
*/
private Long permissionsId;
/**
* @备注:角色名称
* @字段:roles_name VARCHAR(100)
*/
private String rolesName;
/**
* @备注:api接口
* @字段:url VARCHAR(512)
*/
private String url;
}
package webapp.service;
import webapp.model.RolesPermissions;
import java.util.List;
public interface RolesPermissionsService {
List
package webapp.service.impl;
import org.springframework.stereotype.Service;
import webapp.model.RolesPermissions;
import webapp.service.RolesPermissionsService;
import java.util.LinkedList;
import java.util.List;
@Service
public class RolesPermissionsServiceImpl implements RolesPermissionsService {
@Override
public List
package webapp.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import webapp.service.UserService;
import javax.annotation.Resource;
import java.io.Serializable;
/**
* Created by Administrator on 2018/9/5.
*/
@RestController
@RequestMapping("/core/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 登录
* @param
* @return
*/
@GetMapping("/login")
public String login(String userName, String password) {
System.out.println("登录" + userName);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("admin-pc==" + userName, password);
subject.login(token);
Session session = subject.getSession();
Serializable sessionId = session.getId();
System.out.println("登录成功 -> " + sessionId);
return userName + "[" + sessionId + "]";
}
@GetMapping("/logout")
public String logout() {
SecurityUtils.getSubject().logout();
return "退出登录成功";
}
/**
* 获取当前登录用户
* @return
*/
@GetMapping("/findUser")
public String findUser() {
Subject subject = SecurityUtils.getSubject();
PrincipalCollection collection = subject.getPrincipals();
if (null != collection && !collection.isEmpty()) {
String userName = (String) collection.iterator().next();
System.out.println("获取当前登录用户" + userName);
return userService.findOneByUserName(userName).toString();
}
return "{\n" +
" \"codeEnum\": \"OVERTIME\",\n" +
" \"code\": 0,\n" +
" \"data\": null,\n" +
" \"msg\": \"未登陆/登陆超时\",\n" +
" \"success\": false\n" +
"}";
}
}
package webapp.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.springframework.beans.factory.annotation.Autowired;
import webapp.model.RolesPermissions;
import webapp.model.User;
import webapp.service.RolesPermissionsService;
import webapp.service.UserService;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by Administrator on 2018/9/5.
*/
public class UserShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private SessionDAO sessionDAO;
@Autowired
private RolesPermissionsService rolesPermissionsService;
/**
* 角色权限和对应权限添加
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName = (String) principalCollection.getPrimaryPrincipal();
if (userName == null || "".equals(userName)) {
return null;
}else{
userName = userName.split("==")[1];
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
try{
List
package webapp.shiro;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import webapp.model.RolesPermissions;
import webapp.redis.RedisCache;
import webapp.service.RolesPermissionsService;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class CustomRolesAuthorizationFilter extends AuthorizationFilter {
//项目名-用于多项目共用redis缓存时区分项目
private static final String PROJECTNAME = "shiro5";
private RolesPermissionsService rolesPermissionsService;
private RedisCache redisCache;
public CustomRolesAuthorizationFilter(RolesPermissionsService rolesPermissionsService, RedisCache redisCache) {
this.rolesPermissionsService = rolesPermissionsService;
this.redisCache = redisCache;
}
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
Subject subject = getSubject(request, response);
PrincipalCollection principals = subject.getPrincipals();
//未登录情况
if (null == principals) {
return false;
}
String userName = principals.toString();
String userName0 = userName.split("==")[0];
String[] rolesArray = (String[]) mappedValue;
if (rolesArray == null || rolesArray.length == 0) {
return true;
}
//当前请求URI所需要的角色
List
package webapp.shiro;
import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
import org.springframework.util.CollectionUtils;
import webapp.model.RolesPermissions;
import webapp.service.RolesPermissionsService;
import java.util.*;
public class ShiroPermissionFactory extends ShiroFilterFactoryBean {
/**记录配置中的过滤链*/
public static String definition = "";
private RolesPermissionsService rolesPermissionsService;
public ShiroPermissionFactory(RolesPermissionsService rolesPermissionsService){
this.rolesPermissionsService = rolesPermissionsService;
}
/**
* 初始化设置过滤链
*/
@Override
public void setFilterChainDefinitions(String definitions) {
definition = definitions;//记录配置的静态过滤链
List
package webapp.conf;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import webapp.redis.RedisCache;
import webapp.redis.RedisSessionDAO;
import webapp.service.impl.RolesPermissionsServiceImpl;
import webapp.shiro.CustomRolesAuthorizationFilter;
import webapp.shiro.ShiroPermissionFactory;
import webapp.shiro.UserShiroRealm;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
/**
* shiro配置类
* Created by Administrator on 2018/9/5.
*/
@Configuration
public class ShiroConfig {
@Bean
public RedisCache redisCache(){
return new RedisCache();
}
//将自己的验证方式加入容器
@Bean
public UserShiroRealm userShiroRealm() {
return new UserShiroRealm();
}
@Bean
public RedisSessionDAO redisSessionDAO() {
return new RedisSessionDAO();
}
@Bean
public SimpleCookie getSimpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName("SHRIOSESSIONID");
return simpleCookie;
}
//保证实现了Shiro内部lifecycle函数的bean执行
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
//配置shiro session 的一个管理器
@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
sessionManager.setGlobalSessionTimeout(-1000); //session有效期 默认值1800000 30分钟 1800000毫秒 -1000表示永久
SimpleCookie simpleCookie = getSimpleCookie();
simpleCookie.setHttpOnly(true); //设置js不可读取此Cookie
simpleCookie.setMaxAge(3 * 365 * 24 * 60 * 60); //3年 cookie有前期
sessionManager.setSessionIdCookie(simpleCookie);
return sessionManager;
}
//配置核心安全事务管理器
@Bean(name="securityManager")
public SecurityManager securityManager(@Qualifier("userShiroRealm") UserShiroRealm userShiroRealm,
@Qualifier("sessionManager") DefaultWebSessionManager sessionManager) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(userShiroRealm);
manager.setSessionManager(sessionManager);
return manager;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroPermissionFactory shiroPermissionFactory() {
ShiroPermissionFactory shiroFilter = new ShiroPermissionFactory(new RolesPermissionsServiceImpl());
shiroFilter.setSecurityManager(securityManager());
//登录认证不通过跳转
shiroFilter.setLoginUrl("/loginUnAuth");
//权限认证不通过跳转
shiroFilter.setUnauthorizedUrl("/authorUnAuth");
Map
package webapp.shiro;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Map;
/**
* 当修改用户角色权限时候需要调用reloadFilterChains()来刷新角色权限
*/
@Component
public class FilterChainDefinitions {
@Autowired
private ShiroPermissionFactory permissFactory;
public void reloadFilterChains() {
synchronized (permissFactory) { //强制同步,控制线程安全
AbstractShiroFilter shiroFilter = null;
try {
shiroFilter = (AbstractShiroFilter) permissFactory.getObject();
PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
// 过滤管理器
DefaultFilterChainManager manager = (DefaultFilterChainManager) resolver.getFilterChainManager();
// 清除权限配置
manager.getFilterChains().clear();
permissFactory.getFilterChainDefinitionMap().clear();
// 重新设置权限
permissFactory.setFilterChainDefinitions(ShiroPermissionFactory.definition);//传入配置中的filterchains
Map
package webapp.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import webapp.shiro.FilterChainDefinitions;
@RestController
@RequestMapping("/core/test")
public class TestController {
@Autowired
private FilterChainDefinitions filterChainDefinitions;
@GetMapping("/test")
public void test() {
//设置用户权限
//...
//刷新权限
filterChainDefinitions.reloadFilterChains();
}
}
文章标题:springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
文章链接:http://soscw.com/index.php/essay/99944.html