1、前言
作为一名后盾开发人员,权限这个名词应该算是特地相熟的了。就算是java里的类也有 public、private 等“权限”之分。之前我的项目里始终应用shiro作为权限治理的框架。说实话,shiro确实挺弱小的,然而它也有很多不好的中央。shiro默认的登录地址还是login.jsp,前后端拆散模式应用shiro还要重写好多类;手机端存储用户信息、放弃登录状态等等,对shiro来说也是一个难题。
在分布式我的项目里,比方电商我的项目,其实不太须要明确的权限划分,说白了,我认为没必要做太麻烦的权限治理,所有从简。何况shiro对于springCloud等各种分布式框架来说,几乎就是“劫难”。每个子系统里都要写点shiro的货色,缓缓的,越来越恶心。zuul网关就在这里大显神通了,管制用户的登录,鉴定用户的权限等等。zuul网关管制用户登录,鉴权当前再详说。以上高见。
而后最近我发现了另一个权限框架jcasbin,尽管网上还没有很多对于博客,然而我看了一会就能够应用了。
github地址:https://github.com/casbin/jcasbin
2、筹备
Spring Boot 根底就不介绍了,举荐看这个实战我的项目:
https://github.com/javastacks/spring-boot-best-practice
1、mavan仓库引入
<dependency> <groupId>org.casbin</groupId> <artifactId>jcasbin</artifactId> <version>1.1.0</version></dependency><dependency> <groupId>org.casbin</groupId> <artifactId>jdbc-adapter</artifactId> <version>1.1.0</version></dependency>
2、配置文件
jcasbin把用户的角色、权限信息(拜访门路)搁置在配置文件里,而后通过输出流读取配置文件。次要有两个配置文件:model.conf 和 policy.csv。简略的应用GitHub里都讲了,在此就不再赘述了。
其实也能够读取数据库的角色权限配置。所以咱们能够把对于数据库的信息提取进去,能够进行动静设置。
@Configuration@ConfigurationProperties(prefix = org.jcasbin)public class EnforcerConfigProperties { private String url; private String driverClassName; private String username; private String password; private String modelPath; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getModelPath() { return modelPath; } public void setModelPath(String modelPath) { this.modelPath = modelPath; } @Override public String toString() { return EnforcerConfigProperties [url= + url + , driverClassName= + driverClassName + , username= + username + , password= + password + , modelPath= + modelPath + ]; } }
这样咱们就能够在application.properties里进行相干配置了。model.conf是固定的文件,之间复制过去放在新建的和src同级的文件夹下即可。policy.csv的内容是能够从数据库读取的。
org.jcasbin.url=jdbc:mysql://localhost:3306/casbin?useSSL=falseorg.jcasbin.driver-class-name=com.mysql.jdbc.Driverorg.jcasbin.username=rootorg.jcasbin.password=rootorg.jcasbin.model-path=conf/authz_model.conf
3、读取权限信息进行初始化
咱们要对Enforcer这个类初始化,加载配置文件里的信息。所以咱们写一个类实现InitializingBean,在容器加载的时候就初始化这个类,不便后续的应用。
@Componentpublic class EnforcerFactory implements InitializingBean { private static Enforcer enforcer; @Autowired private EnforcerConfigProperties enforcerConfigProperties; private static EnforcerConfigProperties config; @Override public void afterPropertiesSet() throws Exception { config = enforcerConfigProperties; //从数据库读取策略 JDBCAdapter jdbcAdapter = new JDBCAdapter(config.getDriverClassName(),config.getUrl(),config.getUsername(), config.getPassword(), true); enforcer = new Enforcer(config.getModelPath(), jdbcAdapter); enforcer.loadPolicy();//Load the policy from DB. } /** * 增加权限 * @param policy * @return */ public static boolean addPolicy(Policy policy){ boolean addPolicy = enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct()); enforcer.savePolicy(); return addPolicy; } /** * 删除权限 * @param policy * @return */ public static boolean removePolicy(Policy policy){ boolean removePolicy = enforcer.removePolicy(policy.getSub(),policy.getObj(),policy.getAct()); enforcer.savePolicy(); return removePolicy; } public static Enforcer getEnforcer(){ return enforcer; } }
在这个类里,咱们注入写好的配置类,而后转为动态的,在afterPropertiesSet办法里实例化Enforcer并加载policy(策略,角色权限/url对应关系)。
同时又写了两个办法,用来增加和删除policy,Policy是自定的一个类,对官网应用的汇合/数组进行了封装。
public class Policy { /**想要拜访资源的用户 或者角色*/ private String sub; /**将要拜访的资源,能够应用 * 作为通配符,例如/user/* */ private String obj; /**用户对资源执行的操作。HTTP办法,GET、POST、PUT、DELETE等,能够应用 * 作为通配符*/ private String act; public Policy() { super(); } /** * * @param sub 想要拜访资源的用户 或者角色 * @param obj 将要拜访的资源,能够应用 * 作为通配符,例如/user/* * @param act 用户对资源执行的操作。HTTP办法,GET、POST、PUT、DELETE等,能够应用 * 作为通配符 */ public Policy(String sub, String obj, String act) { super(); this.sub = sub; this.obj = obj; this.act = act; } public String getSub() { return sub; } public void setSub(String sub) { this.sub = sub; } public String getObj() { return obj; } public void setObj(String obj) { this.obj = obj; } public String getAct() { return act; } public void setAct(String act) { this.act = act; } @Override public String toString() { return Policy [sub= + sub + , obj= + obj + , act= + act + ]; } }
4、应用
1、权限管制
jcasbin的权限管制非常简单,自定义一个过滤器,if判断就能够搞定,没错,就这么简略。
@WebFilter(urlPatterns = /* , filterName = JCasbinAuthzFilter)@Order(Ordered.HIGHEST_PRECEDENCE)//执行程序,最高级别最先执行,int从小到大public class JCasbinAuthzFilter implements Filter { private static final Logger log = LoggerFactory.getLogger(JCasbinAuthzFilter.class); private static Enforcer enforcer; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String user = request.getParameter(username); String path = request.getRequestURI(); String method = request.getMethod(); enforcer = EnforcerFactory.getEnforcer(); if (path.contains(anon)) { chain.doFilter(request, response); }else if (enforcer.enforce(user, path, method)) { chain.doFilter(request, response); } else { log.info(无权拜访); Map<String, Object> result = new HashMap<String, Object>(); result.put(code, 1001); result.put(msg, 用户权限有余); result.put(data,null); response.setCharacterEncoding(UTF-8); response.setContentType(application/json); response.getWriter().write(JSONObject.toJSONString(result,SerializerFeature.WriteMapNullValue)); } } @Override public void destroy() { } }
次要是用enforcer.enforce(user, path, method)这个办法对用户、拜访资源、形式进行匹配。这里的逻辑能够依据本人的业务来实现。在这个过滤器之前还能够增加一个判断用户是否登录的过滤器。
2、增加删除权限
对于权限的操作,间接调用下面写好的EnforcerFactory里对应的办法即可。并且,能够达到同步的成果。就是不必重启服务器或者其余任何操作,增加或删除用户权限后,用户对应的拜访就会收到影响。
@PutMapping(/anon/role/per) public ResultBO<Object> addPer(){ EnforcerFactory.addPolicy(new Policy(alice, /user/list, *)); return ResultTool.success(); } @DeleteMapping(/anon/role/per) public ResultBO<Object> deletePer(){ EnforcerFactory.removePolicy(new Policy(alice, /user/list, *)); return ResultTool.success(); }
5、最初
其实能够把jcasbin和SpringCloud的zuul联合来实现用户的对立登录和权限管制。自定义一个过滤器继承ZuulFilter即可,其余中央根本没啥区别。这个当前再写。
版权申明:本文为CSDN博主「红藕香残玉簟秋」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/WayneLee0809/article/details/85702551
近期热文举荐:
1.1,000+ 道 Java面试题及答案整顿(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!
5.《Java开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞+转发哦!