一般的內部管理系統,權限比較複雜,通常權限都是動態配置的,也就是下面我們要講的的rbac模型
RBAC
詳細原理請度娘,這裏只是涉及到企業權限的功能級權限,數據級權限還要我們自己控制(用戶只能看見它相關的業務表數據)
Spring Security中支持我們自定義的實現,就像這樣調用,下面我們來代碼實現
config.anyRequest().access("@rbacService.hasPermission(request,authentication)")
權限控制
新建一個authorize項目實現rbac權限,pom文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>tiger-auth</artifactId>
<groupId>com.rui.tiger</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.rui.tiger</groupId>
<artifactId>tiger-auth-authorize</artifactId>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
</dependencies>
</project>
定義rbac接口及實現
package com.rui.tiger.auth.authorize.service;
import org.springframework.security.core.Authentication;
import javax.servlet.http.HttpServletRequest;
/**
* 用戶權限判斷接口
* @author CaiRui
* @date 2019-05-07 08:02
*/
public interface RbacService {
boolean hasPermission(HttpServletRequest request, Authentication authentication);
}
package com.rui.tiger.auth.authorize.service;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author CaiRui
* @date 2019-05-07 08:05
*/
@Component("rbacService")
public class RbacServiceImpl implements RbacService {
private AntPathMatcher antPathMatcher=new AntPathMatcher();
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object principal = authentication.getPrincipal();
boolean hasPermission = false;
if (principal instanceof UserDetails) {
String username = ((UserDetails) principal).getUsername();
//讀取用戶所擁有權限的所有URL 這個應該根據用戶名從數據庫中查詢 此處只是模擬
List<String> urls = new ArrayList<>();
for (String url : urls) {
//匹配 /user/* 這種格式
if (antPathMatcher.match(url, request.getRequestURI())) {
hasPermission = true;
break;
}
}
}
return hasPermission;
}
}
demo項目中引入此依賴,並配置
package com.rui.tiger.auth.demo.security;
import com.rui.tiger.auth.core.authorize.AuthorizeConfigProvider;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.stereotype.Component;
/**
* 業務模塊權限配置實現
* @author CaiRui
* @date 2019-05-06 12:16
*/
@Component
@Order(Integer.MAX_VALUE)
public class DemoAuthorizeConfigProvider implements AuthorizeConfigProvider {
@Override
public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
config.antMatchers(
"/user/regist", // 註冊請求
"/error",
"/connect/*",
"/auth/*",
"/signin",
"/social/signUp", // app註冊跳轉服務
"/swagger-ui.html",
"/swagger-ui.html/**",
"/webjars/**",
"/swagger-resources/**",
"/v2/**"
).permitAll();
/*
利用@Order註解實現CommonAuthorizeConfigProvider中的放行路徑不需要自定義權限驗證
*/
config.anyRequest()
.access("@rbacService.hasPermission(request,authentication)");
return true;
}
}