Commit addacedb authored by maqing's avatar maqing

垂直越权

parent 956022c8
......@@ -29,6 +29,10 @@ public interface AuthConstants {
* Redis缓存权限规则key
*/
String PERMISSION_ROLES_KEY = "ltc:auth:permission:roles";
/**
* Redis缓存权限规则key
*/
String PERMISSION_ROLES_interface_KEY = "ltc:auth:permission:interface";
/**
......
package com.hungraim.ltc.pojo.entity.system;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("LTC_INTERFACE")
public class SystemInterface {
@TableId
private Long interfaceId;
private String interfaceUrl;
private String interfaceName;
private Date createdTime;
}
......@@ -3,6 +3,7 @@ package com.hungraim.ltc.gateway.security;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.hungraim.ltc.constant.AuthConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -13,6 +14,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
......@@ -45,6 +47,7 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
String path = request.getMethodValue() + "_" + request.getURI().getPath();
log.info("请求,path={}", path);
......@@ -62,6 +65,14 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
log.info("请求token为空拒绝访问,path={}", path);
return Mono.just(new AuthorizationDecision(false));
}
String subToken = token.substring(AuthConstants.JWT_PREFIX.length());
String claims = JwtHelper.decode(subToken).getClaims();
String jti = (String) JSONObject.parseObject(claims).get("jti");
String acc_token = (String) redisTemplate.opsForValue().get(jti);
if (!StrUtil.isBlank(acc_token)) {
log.info("请求token为空拒绝访问,path={}", path);
return Mono.just(new AuthorizationDecision(false));
}
// 从缓存取资源权限角色关系列表
......
package com.hungraim.ltc.component;
import com.hungraim.ltc.system.service.impl.SystemInterfaceServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
*
* 服务运行时将资源和接口关系缓存到数据库中
* @author mq
*/
@Component
@Slf4j
public class InitResourceInterfaceCacheRunner implements CommandLineRunner {
private final SystemInterfaceServiceImpl systemInterfaceService;
@Autowired
public InitResourceInterfaceCacheRunner( SystemInterfaceServiceImpl systemInterfaceService) {
this.systemInterfaceService = systemInterfaceService;
}
@Override
public void run(String... args){
systemInterfaceService.refreshResourceInterfaceCache();
}
}
package com.hungraim.ltc.system.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hungraim.ltc.pojo.entity.system.SystemInterface;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 查询所有资源对应的接口
* @return 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);
/**
* 根据资源id查找接口id
*
* @return 角色id
*/
@Select("SELECT INTERFACE_ID FROM LTC_RESOURCE_INTERFACE")
List<Long> listRI();
}
......@@ -17,9 +17,9 @@ public interface SystemResourceMapper extends BaseMapper<SystemResource> {
* 查询所有资源对应的角色
* @return list
*/
@Select("SELECT RESOURCE_ID,RESOURCE_NAME,RESOURCE_URL,METHOD FROM LTC_RESOURCE")
@Select("SELECT RESOURCE_ID as resourceId,RESOURCE_ID,RESOURCE_NAME,RESOURCE_URL,METHOD FROM LTC_RESOURCE")
@Results({
@Result(property = "roleIds", column = "RESOURCE_ID",many = @Many(select = "com.hungraim.ltc.system.dao.SystemRoleResourceMapper.listRoleIds"))
@Result(property = "roleIds", column = "resourceId",many = @Many(select = "com.hungraim.ltc.system.dao.SystemRoleResourceMapper.listRoleIds"))
})
List<SystemResource> listResourceRoles();
......
package com.hungraim.ltc.system.service;
import com.hungraim.ltc.pojo.entity.system.SystemInterface;
import java.util.List;
import java.util.Map;
public interface ISystemInterfaceService {
/**
* 将mysql中的接口资源关系缓存到redis中
*/
void refreshResourceInterfaceCache();
/**
* 查询所有资源对应的接口
* @return list
*/
List<String> listResourceInterface(Long resourceId);
}
package com.hungraim.ltc.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hungraim.ltc.constant.AuthConstants;
import com.hungraim.ltc.pojo.entity.system.SystemInterface;
import com.hungraim.ltc.system.dao.SystemInterfaceMapper;
import com.hungraim.ltc.system.service.ISystemInterfaceService;
import lombok.extern.slf4j.Slf4j;
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;
@Service
@Slf4j
public class SystemInterfaceServiceImpl extends ServiceImpl<SystemInterfaceMapper, SystemInterface> implements ISystemInterfaceService {
private final SystemInterfaceMapper systemInterfaceMapper;
private final RedisTemplate redisTemplate;
@Autowired
public SystemInterfaceServiceImpl(SystemInterfaceMapper systemInterfaceMapper, RedisTemplate redisTemplate) {
this.systemInterfaceMapper = systemInterfaceMapper;
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);
}
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_interface_KEY, map);
}catch (RuntimeException e){
e.printStackTrace();
}
}
@Override
public List<String> listResourceInterface(Long interfaceId) {
return systemInterfaceMapper.listInterface(interfaceId);
}
}
......@@ -22,10 +22,12 @@ import java.util.stream.Collectors;
public class SystemResourceServiceImpl extends ServiceImpl<SystemResourceMapper, SystemResource> implements ISystemResourceService {
private final SystemResourceMapper systemResourceMapper;
private final RedisTemplate redisTemplate;
@Autowired
public SystemResourceServiceImpl(RedisTemplate redisTemplate) {
public SystemResourceServiceImpl(SystemResourceMapper systemResourceMapper, RedisTemplate redisTemplate) {
this.systemResourceMapper = systemResourceMapper;
this.redisTemplate = redisTemplate;
}
......@@ -36,27 +38,31 @@ public class SystemResourceServiceImpl extends ServiceImpl<SystemResourceMapper,
@Override
@SuppressWarnings("unchecked")
public void refreshPermissionRolesCache(){
log.info("refreshPermissionRolesCache run...");
redisTemplate.delete(AuthConstants.PERMISSION_ROLES_KEY);
List<SystemResource> permissions = this.listResourceRoles();
Map<String, List<String>> permissionRoles = new TreeMap<>();
Optional.ofNullable(permissions).orElse(new ArrayList<>()).forEach(permission -> {
// 转换 roleId -> ROLE_{roleId}
List<String> roles = Optional.ofNullable(permission.getRoleIds())
.orElse(new ArrayList<>())
.stream()
.map(roleId -> AuthConstants.AUTHORITY_PREFIX + roleId)
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(roles)) {
permissionRoles.put(permission.getMethod() +"_"+ permission.getResourceUrl(), roles);
}
});
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_KEY, permissionRoles);
try {
log.info("refreshPermissionRolesCache run...");
redisTemplate.delete(AuthConstants.PERMISSION_ROLES_KEY);
List<SystemResource> permissions = this.listResourceRoles();
Map<String, List<String>> permissionRoles = new TreeMap<>();
Optional.ofNullable(permissions).orElse(new ArrayList<>()).forEach(permission -> {
// 转换 roleId -> ROLE_{roleId}
List<String> roles = Optional.ofNullable(permission.getRoleIds())
.orElse(new ArrayList<>())
.stream()
.map(roleId -> AuthConstants.AUTHORITY_PREFIX + roleId)
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(roles)) {
permissionRoles.put(permission.getResourceId().toString(), roles);
}
});
redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_KEY, permissionRoles);
}catch (RuntimeException e) {
e.printStackTrace();
}
}
@Override
public List<SystemResource> listResourceRoles() {
return this.baseMapper.listResourceRoles();
return systemResourceMapper.listResourceRoles();
}
......
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