springboot整合jcasbin權(quán)限管理
前言
作為一名后臺(tái)開發(fā)人員,權(quán)限這個(gè)名詞應(yīng)該算是特別熟悉的了。就算是java里的類也有 public、private 等“權(quán)限”之分。之前項(xiàng)目里一直使用shiro作為權(quán)限管理的框架。說(shuō)實(shí)話,shiro的確挺強(qiáng)大的,但是它也有很多不好的地方。shiro默認(rèn)的登錄地址還是login.jsp,前后端分離模式使用shiro還要重寫好多類;手機(jī)端存儲(chǔ)用戶信息、保持登錄狀態(tài)等等,對(duì)shiro來(lái)說(shuō)也是一個(gè)難題。
在分布式項(xiàng)目里,比如電商項(xiàng)目,其實(shí)不太需要明確的權(quán)限劃分,說(shuō)白了,我認(rèn)為沒(méi)必要做太麻煩的權(quán)限管理,一切從簡(jiǎn)。何況shiro對(duì)于springCloud等各種分布式框架來(lái)說(shuō),簡(jiǎn)直就是“災(zāi)難”。每個(gè)子系統(tǒng)里都要寫點(diǎn)shiro的東西,慢慢的,越來(lái)越惡心。zuul網(wǎng)關(guān)就在這里大顯身手了,控制用戶的登錄,鑒定用戶的權(quán)限等等。zuul網(wǎng)關(guān)控制用戶登錄,鑒權(quán)以后再詳說(shuō)。以上拙見。
然后最近我發(fā)現(xiàn)了另一個(gè)權(quán)限框架jcasbin,雖然網(wǎng)上還沒(méi)有很多關(guān)于博客,但是我看了一會(huì)就可以使用了。
順手貼上github地址:https://github.com/casbin/jcasbin
一、準(zhǔn)備
基于springboot1.5.10,但是和springboot關(guān)系不太大。
1、mavan倉(cāng)庫(kù)引入
? ? ? ?<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把用戶的角色、權(quán)限信息(訪問(wèn)路徑)放置在配置文件里,然后通過(guò)輸入流讀取配置文件。主要有兩個(gè)配置文件:model.conf 和 policy.csv。簡(jiǎn)單的使用GitHub里都講了,在此就不再贅述了。
其實(shí)也可以讀取數(shù)據(jù)庫(kù)的角色權(quán)限配置。所以我們可以把關(guān)于數(shù)據(jù)庫(kù)的信息提取出來(lái),可以進(jìn)行動(dòng)態(tài)設(shè)置。
@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里進(jìn)行相關(guān)配置了。model.conf是固定的文件,之間復(fù)制過(guò)來(lái)放在新建的和src同級(jí)的文件夾下即可。policy.csv的內(nèi)容是可以從數(shù)據(jù)庫(kù)讀取的。
org.jcasbin.url=jdbc:mysql://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
二、讀取權(quán)限信息進(jìn)行初始化
我們要對(duì)Enforcer這個(gè)類初始化,加載配置文件里的信息。所以我們寫一個(gè)類實(shí)現(xiàn)InitializingBean,在容器加載的時(shí)候就初始化這個(gè)類,方便后續(xù)的使用。
@Component
public class EnforcerFactory implements InitializingBean {
private static Enforcer enforcer;
@Autowired
private EnforcerConfigProperties enforcerConfigProperties;
private static EnforcerConfigProperties config;
@Override
public void afterPropertiesSet() throws Exception {
config = enforcerConfigProperties;
//從數(shù)據(jù)庫(kù)讀取策略
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.
}
/**
* 添加權(quán)限
* @param policy
* @return
*/
public static boolean addPolicy(Policy policy){
boolean addPolicy = enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct());
enforcer.savePolicy();
return addPolicy;
}
/**
* 刪除權(quán)限
* @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;
}
}在這個(gè)類里,我們注入寫好的配置類,然后轉(zhuǎn)為靜態(tài)的,在afterPropertiesSet方法里實(shí)例化Enforcer并加載policy(策略,角色權(quán)限/url對(duì)應(yīng)關(guān)系)。
同時(shí)又寫了兩個(gè)方法,用來(lái)添加和刪除policy,Policy是自定的一個(gè)類,對(duì)官方使用的集合/數(shù)組進(jìn)行了封裝。
public class Policy {
/**想要訪問(wèn)資源的用戶 或者角色*/
private String sub;
/**將要訪問(wèn)的資源,可以使用 * 作為通配符,例如/user/* */
private String obj;
/**用戶對(duì)資源執(zhí)行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用 * 作為通配符*/
private String act;
public Policy() {
super();
}
/**
*
* @param sub 想要訪問(wèn)資源的用戶 或者角色
* @param obj 將要訪問(wèn)的資源,可以使用 * 作為通配符,例如/user/*
* @param act 用戶對(duì)資源執(zhí)行的操作。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 + "]";
}
}三、使用
1、權(quán)限控制
jcasbin的權(quán)限控制非常簡(jiǎn)單,自定義一個(gè)過(guò)濾器,if判斷就可以搞定,沒(méi)錯(cuò),就這么簡(jiǎn)單。
@WebFilter(urlPatterns = "/*" , filterName = "JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)//執(zhí)行順序,最高級(jí)別最先執(zhí)行,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("無(wú)權(quán)訪問(wèn)");
Map<String, Object> result = new HashMap<String, Object>();
result.put("code", 1001);
result.put("msg", "用戶權(quán)限不足");
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)這個(gè)方法對(duì)用戶、訪問(wèn)資源、方式進(jìn)行匹配。這里的邏輯可以根據(jù)自己的業(yè)務(wù)來(lái)實(shí)現(xiàn)。在這個(gè)過(guò)濾器之前還可以添加一個(gè)判斷用戶是否登錄的過(guò)濾器。
2、添加刪除權(quán)限
對(duì)于權(quán)限的操作,直接調(diào)用上面寫好的EnforcerFactory里對(duì)應(yīng)的方法即可。并且,可以達(dá)到同步的效果。就是不用重啟服務(wù)器或者其他任何操作,添加或刪除用戶權(quán)限后,用戶對(duì)應(yīng)的訪問(wèn)就會(huì)收到影響。
@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();
}寫在后面的話
其實(shí)可以把jcasbin和SpringCloud的zuul結(jié)合來(lái)實(shí)現(xiàn)用戶的統(tǒng)一登錄和權(quán)限控制。自定義一個(gè)過(guò)濾器繼承ZuulFilter即可,其他地方基本沒(méi)啥區(qū)別。這個(gè)以后再寫。
到此這篇關(guān)于springboot整合jcasbin權(quán)限管理的文章就介紹到這了,更多相關(guān)springboot jcasbin權(quán)限內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- spring?boot權(quán)限管理的幾種常見方式
- SpringBoot和Vue.js實(shí)現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng)
- springboot集成shiro權(quán)限管理簡(jiǎn)單實(shí)現(xiàn)
- springboot實(shí)戰(zhàn)權(quán)限管理功能圖文步驟附含源碼
- Spring?boot?security權(quán)限管理集成cas單點(diǎn)登錄功能的實(shí)現(xiàn)
- 詳解springboot shiro jwt實(shí)現(xiàn)權(quán)限管理
- SpringBoot整合Shiro框架,實(shí)現(xiàn)用戶權(quán)限管理
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
- SpringBoot中整合Shiro實(shí)現(xiàn)權(quán)限管理的示例代碼
- SpringBoot2.0整合Shiro框架實(shí)現(xiàn)用戶權(quán)限管理的示例
相關(guān)文章
淺析java中ArrayList與Vector的區(qū)別以及HashMap與Hashtable的區(qū)別
以下是對(duì)java中ArrayList與Vector的區(qū)別以及HashMap與Hashtable的區(qū)別進(jìn)行了詳細(xì)的解析。需要的朋友可以過(guò)來(lái)參考下2013-08-08
Java超詳細(xì)講解SpringMVC如何獲取請(qǐng)求數(shù)據(jù)
Spring?MVC?是?Spring?提供的一個(gè)基于?MVC?設(shè)計(jì)模式的輕量級(jí)?Web?開發(fā)框架,本質(zhì)上相當(dāng)于?Servlet,Spring?MVC?角色劃分清晰,分工明細(xì),本章來(lái)講解SpringMVC如何獲取請(qǐng)求數(shù)據(jù)2022-04-04
java數(shù)據(jù)庫(kù)連接池新手入門一篇就夠了,太簡(jiǎn)單了!
數(shù)據(jù)庫(kù)連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫(kù)連接,釋放空閑時(shí)間超過(guò)最大空閑時(shí)間的數(shù)據(jù)庫(kù)連接來(lái)避免因?yàn)闆](méi)有釋放數(shù)據(jù)庫(kù)連接而引起的數(shù)據(jù)庫(kù)連接遺漏,這項(xiàng)技術(shù)能明顯提高對(duì)數(shù)據(jù)庫(kù)操作的性能2021-06-06
解決Spring Boot 多模塊注入訪問(wèn)不到j(luò)ar包中的Bean問(wèn)題
這篇文章主要介紹了解決Spring Boot 多模塊注入訪問(wèn)不到j(luò)ar包中的Bean問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09

