Commit f05cb559 authored by maqing's avatar maqing

垂直越权

parent addacedb
......@@ -32,7 +32,12 @@ public interface AuthConstants {
/**
* Redis缓存权限规则key
*/
String PERMISSION_ROLES_interface_KEY = "ltc:auth:permission:interface";
String PERMISSION_RESOURCE_INTERFACE_KEY = "ltc:resource:interface";
/**
* Redis缓存权限规则key
*/
String PERMISSION_ROLES_RESOURCE_KEY = "ltc:roles:resource";
/**
......
......@@ -51,11 +51,12 @@ public class ResourceServerConfig {
http.oauth2ResourceServer().jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter());
http.authorizeExchange()
.pathMatchers("/api/oauth/token","/oauth/*","/api/oauth/genKeyPair").permitAll()
.pathMatchers("/api/oauth/token","/api.system/role/getRoleResource",
"/api.system/resource/getManinMenu","/oauth/*","/api/oauth/genKeyPair").permitAll()
.anyExchange().access(authorizationManager)
.and()
.exceptionHandling()
// 处理未授权
// 处理
.accessDeniedHandler(accessDeniedHandler())
//处理未认证
.authenticationEntryPoint(authenticationEntryPoint())
......
......@@ -5,7 +5,9 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.hungraim.ltc.constant.AuthConstants;
import com.hungraim.ltc.pojo.entity.system.SystemInterface;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
......@@ -21,10 +23,7 @@ import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import reactor.core.publisher.Mono;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* 鉴权管理器
......@@ -74,41 +73,38 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
return Mono.just(new AuthorizationDecision(false));
}
// 从缓存取资源权限角色关系列表
Map<Object, Object> permissionRoles = redisTemplate.opsForHash().entries(AuthConstants.PERMISSION_ROLES_KEY);
Iterator<Object> iterator = permissionRoles.keySet().iterator();
// 请求路径匹配到的资源需要的角色权限集合authorities统计
Set<String> authorities = new HashSet<>();
while (iterator.hasNext()) {
String pattern = (String) iterator.next();
if (pathMatcher.match(pattern, path)) {
authorities.addAll(Convert.toList(String.class, permissionRoles.get(pattern)));
}
}
log.info("require authorities:{}", authorities);
// 认证通过且角色匹配的用户可访问当前路径
// return mono.map(auth -> {
// return new AuthorizationDecision(true);
// }).defaultIfEmpty(new AuthorizationDecision(false));
return mono
.filter(Authentication::isAuthenticated)
Mono<AuthorizationDecision> authorizationDecisionMono = mono.filter(Authentication::isAuthenticated)
.flatMapIterable(Authentication::getAuthorities)
.map(GrantedAuthority::getAuthority)
.any(roleId -> {
// roleId是请求用户的角色(格式:ROLE_{roleId}),authorities是请求资源所需要角色的集合
log.info("访问路径:{}", path);
log.info("用户角色信息:{}", roleId);
log.info("资源需要权限authorities:{}", authorities);
//如果是管理员 直接放行
if ("ROLE_0".equals(roleId)) {
return true;
}
String[] splitpath = path.split("/");
String pathNew = "/" + splitpath[1] + "/" + splitpath[2] + "/*";
Set<String> authorities = new HashSet<>();
Map<String, List<Long>> rolesResources = redisTemplate.opsForHash().entries(AuthConstants.PERMISSION_ROLES_RESOURCE_KEY);
Map<String, List<SystemInterface>> interfaces = redisTemplate.opsForHash().entries(AuthConstants.PERMISSION_RESOURCE_INTERFACE_KEY);
List<Long> resources = rolesResources.get(roleId);
for (Long resource : resources) {
List<SystemInterface> systemInterfaces = interfaces.get(resource.toString());
if (systemInterfaces != null && systemInterfaces.size() > 0) {
for (SystemInterface iter : systemInterfaces) {
if (pathMatcher.match(iter.getInterfaceUrl(), pathNew)) {
authorities.addAll(Convert.toList(String.class, roleId));
}
}
}
}
log.info("资源需要权限authorities:{}", authorities);
return authorities.contains(roleId);
})
.map(AuthorizationDecision::new)
.defaultIfEmpty(new AuthorizationDecision(false));
return authorizationDecisionMono;
}
}
......@@ -24,6 +24,6 @@ public class InitResourceInterfaceCacheRunner implements CommandLineRunner {
@Override
public void run(String... args){
systemInterfaceService.refreshResourceInterfaceCache();
systemInterfaceService.listResourceInterface();
}
}
......@@ -2,6 +2,7 @@ package com.hungraim.ltc.system.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hungraim.ltc.pojo.entity.system.SystemInterface;
import com.hungraim.ltc.pojo.entity.system.SystemResource;
import org.apache.ibatis.annotations.*;
import java.util.List;
......@@ -13,17 +14,14 @@ import java.util.List;
@Mapper
public interface SystemInterfaceMapper extends BaseMapper<SystemInterface> {
@Select("SELECT a.INTERFACE_URL FROM " +
"LTC_INTERFACE a where a.INTERFACE_ID= #{interfaceId}")
List<String> listInterface(long interfaceId);
@Select("SELECT a.INTERFACE_ID,a.INTERFACE_URL FROM LTC_INTERFACE a,LTC_RESOURCE_INTERFACE e where a.INTERFACE_ID=e.INTERFACE_ID and e.RESOURCE_ID=#{resourceId}")
List<SystemInterface> listInterface(Long resourceId);
/**
* 根据资源id查找接口id
*
* @return 角色id
*/
@Select("SELECT INTERFACE_ID FROM LTC_RESOURCE_INTERFACE")
List<Long> listRI();
@Select("select b.ROLE_ID from LTC_ROLE b")
List<Long> listRole();
@Select("select c.RESOURCE_ID from LTC_ROLE_RESOURCE c WHERE c.ROLE_ID=#{roleId}")
List<Long> listRoleResource(Long roleId);
}
......@@ -8,13 +8,8 @@ import java.util.Map;
public interface ISystemInterfaceService {
/**
* 将mysql中的接口资源关系缓存到redis中
*/
void refreshResourceInterfaceCache();
/**
* 查询所有资源对应的接口
* @return list
*/
List<String> listResourceInterface(Long resourceId);
void listResourceInterface();
}
......@@ -10,43 +10,53 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author mq
*/
@Service
@Slf4j
public class SystemInterfaceServiceImpl extends ServiceImpl<SystemInterfaceMapper, SystemInterface> implements ISystemInterfaceService {
private final SystemInterfaceMapper systemInterfaceMapper;
private final SystemResourceServiceImpl systemResourceService;
private final RedisTemplate redisTemplate;
@Autowired
public SystemInterfaceServiceImpl(SystemInterfaceMapper systemInterfaceMapper, RedisTemplate redisTemplate) {
public SystemInterfaceServiceImpl(SystemInterfaceMapper systemInterfaceMapper, SystemResourceServiceImpl systemResourceService, RedisTemplate redisTemplate) {
this.systemInterfaceMapper = systemInterfaceMapper;
this.systemResourceService = systemResourceService;
this.redisTemplate = redisTemplate;
}
@Override
public void refreshResourceInterfaceCache() {
try{
redisTemplate.delete(AuthConstants.PERMISSION_ROLES_interface_KEY);
Map<String, List<String> > map = new HashMap<>();
List<Long> interfaceIds = systemInterfaceMapper.listRI();
for (Long interfaceId:interfaceIds){
List<String> systemInterfaces = this.listResourceInterface(interfaceId);
map.put(interfaceId.toString(),systemInterfaces);
public void listResourceInterface() {
try {
redisTemplate.delete(AuthConstants.PERMISSION_RESOURCE_INTERFACE_KEY);
redisTemplate.delete(AuthConstants.PERMISSION_ROLES_RESOURCE_KEY);
Map<String, List<Long>> roleResourcesMap = new TreeMap<>();
Map<String, List<SystemInterface>> stringStringHashMap = new HashMap<>();
List<Long> roles = systemInterfaceMapper.listRole();
String roleId;
for (Long role : roles) {
List<Long> roleResources = systemInterfaceMapper.listRoleResource(role);
//保存资源和接口
for (Long roleResource:roleResources){
List<SystemInterface> systemInterfaces=systemInterfaceMapper.listInterface(roleResource);
stringStringHashMap.put(roleResource.toString(),systemInterfaces);
}
// 转换 roles -> ROLE_{roleId}
roleId=AuthConstants.AUTHORITY_PREFIX + role;
//保存角色和资源
roleResourcesMap.put(roleId,roleResources);
}
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_interface_KEY, map);
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_RESOURCE_KEY, roleResourcesMap);
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_RESOURCE_INTERFACE_KEY, stringStringHashMap);
}catch (RuntimeException e){
e.printStackTrace();
}
}
@Override
public List<String> listResourceInterface(Long interfaceId) {
return systemInterfaceMapper.listInterface(interfaceId);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment