前言
作為一名后臺開發人員,權限這個名詞應該算是特別熟悉的了。就算是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瀏覽量
17476 -
spring
+關注
關注
0文章
340瀏覽量
14340 -
過濾器
+關注
關注
1文章
428瀏覽量
19594
原文標題:再見了 shiro
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論