前言
作为一名后台开发人员,权限这个名词应该算是特别熟悉的了。就算是java里的类也有 public、private 等“权限”之分。之前项目里一直使用shiro作为权限管理的框架。说实话,shiro的确挺强大的,但是它也有很多不好的地方。shiro默认的登录地址还是login.jsp,前后端分离模式使用shiro还要重写好多类;手机端存储用户信息、保持登录状态等等,对shiro来说也是一个难题。
在分布式项目里,比如电商项目,其实不太需要明确的权限划分,说白了,我认为没必要做太麻烦的权限管理,一切从简。何况shiro对于springCloud等各种分布式框架来说,简直就是“灾难”。每个子系统里都要写点shiro的东西,慢慢的,越来越恶心。zuul网关就在这里大显身手了,控制用户的登录,鉴定用户的权限等等。zuul网关控制用户登录,鉴权以后再详说。以上拙见。
然后最近我发现了另一个权限框架jcasbin,虽然网上还没有很多关于博客,但是我看了一会就可以使用了。
顺手贴上github地址:https://github.com/casbin/jcasbin
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
- 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 视频教程:https://doc.iocoder.cn/video/
一、准备
基于springboot1.5.10,但是和springboot关系不太大,所以版本可以忽略,用你熟悉的springboot版本就行。
1、mavan仓库引入
org.casbin
jcasbin
1.1.0
org.casbin
jdbc-adapter
1.1.0
2、配置文件
jcasbin把用户的角色、权限信息(访问路径)放置在配置文件里,然后通过输入流读取配置文件。主要有两个配置文件:model.conf
和 policy.csv
。简单的使用GitHub里都讲了,在此就不再赘述了。
其实也可以读取数据库的角色权限配置。所以我们可以把关于数据库的信息提取出来,可以进行动态设置。
@Configuration
@ConfigurationProperties(prefix="org.jcasbin")
publicclassEnforcerConfigProperties{
privateStringurl;
privateStringdriverClassName;
privateStringusername;
privateStringpassword;
privateStringmodelPath;
publicStringgetUrl(){
returnurl;
}
publicvoidsetUrl(Stringurl){
this.url=url;
}
publicStringgetDriverClassName(){
returndriverClassName;
}
publicvoidsetDriverClassName(StringdriverClassName){
this.driverClassName=driverClassName;
}
publicStringgetUsername(){
returnusername;
}
publicvoidsetUsername(Stringusername){
this.username=username;
}
publicStringgetPassword(){
returnpassword;
}
publicvoidsetPassword(Stringpassword){
this.password=password;
}
publicStringgetModelPath(){
returnmodelPath;
}
publicvoidsetModelPath(StringmodelPath){
this.modelPath=modelPath;
}
@Override
publicStringtoString(){
return"EnforcerConfigProperties[url="+url+",driverClassName="+driverClassName+",username="
+username+",password="+password+",modelPath="+modelPath+"]";
}
}
这样我们就可以在application.properties
里进行相关配置了。model.conf
是固定的文件,之间复制过来放在新建的和src同级的文件夹下即可。policy.csv
的内容是可以从数据库读取的。
org.jcasbin.url=jdbc//localhost:3306/casbin?useSSL=false
org.jcasbin.driver-class-name=com.mysql.jdbc.Driver
org.jcasbin.username=root
org.jcasbin.password=root
org.jcasbin.model-path=conf/authz_model.conf
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
二、读取权限信息进行初始化
我们要对Enforcer
这个类初始化,加载配置文件里的信息。所以我们写一个类实现InitializingBean
,在容器加载的时候就初始化这个类,方便后续的使用。
@Component
publicclassEnforcerFactoryimplementsInitializingBean{
privatestaticEnforcerenforcer;
@Autowired
privateEnforcerConfigPropertiesenforcerConfigProperties;
privatestaticEnforcerConfigPropertiesconfig;
@Override
publicvoidafterPropertiesSet()throwsException{
config=enforcerConfigProperties;
//从数据库读取策略
JDBCAdapterjdbcAdapter=newJDBCAdapter(config.getDriverClassName(),config.getUrl(),config.getUsername(),
config.getPassword(),true);
enforcer=newEnforcer(config.getModelPath(),jdbcAdapter);
enforcer.loadPolicy();//LoadthepolicyfromDB.
}
/**
*添加权限
*@parampolicy
*@return
*/
publicstaticbooleanaddPolicy(Policypolicy){
booleanaddPolicy=enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct());
enforcer.savePolicy();
returnaddPolicy;
}
/**
*删除权限
*@parampolicy
*@return
*/
publicstaticbooleanremovePolicy(Policypolicy){
booleanremovePolicy=enforcer.removePolicy(policy.getSub(),policy.getObj(),policy.getAct());
enforcer.savePolicy();
returnremovePolicy;
}
publicstaticEnforcergetEnforcer(){
returnenforcer;
}
}
在这个类里,我们注入写好的配置类,然后转为静态的,在afterPropertiesSet
方法里实例化Enforcer
并加载policy(策略,角色权限/url对应关系)。
同时又写了两个方法,用来添加和删除policy,Policy是自定的一个类,对官方使用的集合/数组进行了封装。
publicclassPolicy{
/**想要访问资源的用户或者角色*/
privateStringsub;
/**将要访问的资源,可以使用*作为通配符,例如/user/**/
privateStringobj;
/**用户对资源执行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用*作为通配符*/
privateStringact;
publicPolicy(){
super();
}
/**
*
*@paramsub想要访问资源的用户或者角色
*@paramobj将要访问的资源,可以使用*作为通配符,例如/user/*
*@paramact用户对资源执行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用*作为通配符
*/
publicPolicy(Stringsub,Stringobj,Stringact){
super();
this.sub=sub;
this.obj=obj;
this.act=act;
}
publicStringgetSub(){
returnsub;
}
publicvoidsetSub(Stringsub){
this.sub=sub;
}
publicStringgetObj(){
returnobj;
}
publicvoidsetObj(Stringobj){
this.obj=obj;
}
publicStringgetAct(){
returnact;
}
publicvoidsetAct(Stringact){
this.act=act;
}
@Override
publicStringtoString(){
return"Policy[sub="+sub+",obj="+obj+",act="+act+"]";
}
}
三、使用
1、权限控制
jcasbin的权限控制非常简单,自定义一个过滤器,if判断就可以搞定,没错,就这么简单。
@WebFilter(urlPatterns="/*",filterName="JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)//执行顺序,最高级别最先执行,int从小到大
publicclassJCasbinAuthzFilterimplementsFilter{
privatestaticfinalLoggerlog=LoggerFactory.getLogger(JCasbinAuthzFilter.class);
privatestaticEnforcerenforcer;
@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
}
@Override
publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainchain)
throwsIOException,ServletException{
HttpServletRequestrequest=(HttpServletRequest)servletRequest;
HttpServletResponseresponse=(HttpServletResponse)servletResponse;
Stringuser=request.getParameter("username");
Stringpath=request.getRequestURI();
Stringmethod=request.getMethod();
enforcer=EnforcerFactory.getEnforcer();
if(path.contains("anon")){
chain.doFilter(request,response);
}elseif(enforcer.enforce(user,path,method)){
chain.doFilter(request,response);
}else{
log.info("无权访问");
Mapresult=newHashMap();
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
publicvoiddestroy(){
}
}
主要是用enforcer.enforce(user, path, method)
这个方法对用户、访问资源、方式进行匹配。这里的逻辑可以根据自己的业务来实现。在这个过滤器之前还可以添加一个判断用户是否登录的过滤器。
2、添加删除权限
对于权限的操作,直接调用上面写好的EnforcerFactory
里对应的方法即可。并且,可以达到同步的效果。就是不用重启服务器或者其他任何操作,添加或删除用户权限后,用户对应的访问就会收到影响。
@PutMapping("/anon/role/per")
publicResultBO{
EnforcerFactory.addPolicy(newPolicy("alice","/user/list","*"));
returnResultTool.success();
}
@DeleteMapping("/anon/role/per")
publicResultBO{
EnforcerFactory.removePolicy(newPolicy("alice","/user/list","*"));
returnResultTool.success();
}
写在后面的话
其实可以把jcasbin和SpringCloud的zuul结合来实现用户的统一登录和权限控制。自定义一个过滤器继承ZuulFilter即可,其他地方基本没啥区别。
审核编辑 :李倩
-
框架
+关注
关注
0文章
403浏览量
17478 -
spring
+关注
关注
0文章
340浏览量
14340 -
过滤器
+关注
关注
1文章
428浏览量
19597
原文标题:再见了 shiro
文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论