数据权限 java 开源_open-scope: OpenScope是一种轻量级、易维护的“数据权限”的解决方案,它能处理比较复杂的“数据权限”操作逻辑。兼容Shiro等操作权限框架。...

open-scope

介绍

OpenScope是一种轻量级、易维护的数据权限的解决方案,它能处理比较复杂的权限操作逻辑。兼容操作权限Shiro等框架。

OpenScope提供了一种基于SQL的智能添加权限范围列的方案,相对原始的数据权限方案,它是轻量级的,它只有一些配置代码,同时它也是提高了代码的可维护性。另外它不需要额外的更改您的程序结构,就能轻松使您的项目支持数据权限操作。

什么是操作权限,什么是数据权限详细见WIKI 简介

1.0.0.0.RELEASE 版本功能介绍

支持Mybatis- SQL 根据权限范围列动态数据行过滤(兼容PageHelper,OrderBy等其他Mybatis插件)

支持多个范围类型,多个业务对象指定范围类型。

兼容shiro、spring-security等操作权限框架,也可以独立存在,因为它拥有完善的认证流程。

参数额外支持JSON(spring-web包)

支持自定义错误异常返回,这个异常返回。

1.0.1.0.RELEASE 版本功能介绍

将数据权限的粒度控制到数据列上。[-]

对ORM-HIBERNATE兼容或者对ORM-JDBC(任选其一)[-]

(注:[-] 表示待开发或者正在开发中,[√]表示已完成)

1.0.0.0.RELEASE原理:

ORM-Mybatis过滤原理:通过对SQL智能的添加权限列来到的基于权限范围的数据过滤。

1.0.0.0.RELEASE版本的默认流程:

考虑性能的原因:

我们给了一套默认的权限配置,对查询多条数据只进行数据过滤操作,对单挑数据的操作只执行转换操作和认证操作。这对Spring-Cloud相关的微服务项目很有帮助。减少了各个模块之间相互调用的次数,提升了服务器的处理能力和响应能力。

但是如果您不考虑性能的问题,而是考虑权限认证操作的流程的完整性。你仍然可以为每一个请求开启过滤、转换,认证三个操作。

(注:可以根据业务的范围或者实际需求进行调整,ORM-Mybatis过滤是基于SQL,所以请务必要保证您的查询结果集合里存在配置的范围列字段,否则执行权限范围过滤的过程中会抛出找不到范围列的异常信息。[SQLException: Column 您配置的权限范围列 not found异常。])

组件的过滤流程:

控制层请求 >

控制层切面 >

执行范围提取器获得权限范围 >

将权限范围设置到scopeCollections中 >

进入业务切面 >

将业务切面类上的TableScope内容完善到scopeCollections中 >

进入权限拦截器 >

根据scopeCollections的内容进行智能拼装SQL

组件的认证流程

控制层请求 >

控制层切面 >

进入权限范围转换器 获得业务对象,将业务对象转换成范围对象 >

将范围对象交给权限认证器 >

认证器向您的认证服务中心提供的认证权限的接口发起请求 >

您的具体业务逻辑 >

如果认证器里没有抛出异常,则认证成功 >

如果认证器里抛出异常,则认证失败 >

软件架构

OpenScope分为多个组件

权限范围认证器(IScopeAuthenticator)

主要用于向您的认证中心发起认证消息。你可以在这里面写一些您的认证中心的发起逻辑。

权限范围提取器(IScopeExtractor)

主要用于从您的认证中心提取业务范围数据,并将其设置到List scopeCollections中。用于权限拦截器动态拼装权限范围等内容。

权限范围转换器(IScopeConverter)

主要用于业务对象ID转换范围对象ID。

错误异常处理器(ThrowableHandler)

主要用于统一处理权限认证的错误异常类

ORM-权限拦截器 (Permission)

智能的对SQL进行拦截,并为其添加权限范围过滤列。

子包说明

scope-common (公用的模型定义)

scope-annotation(公用的注解)

scope-orm-mybatis(ORM框架有关的内容)

scope-spring-web(Spring-web相关的内容)

scope-autoconfigure(自动配置内容)

scope-boot-starter(SpringBoot相关内容)

安装方法(SpringBoot)

com.mofum.scope

scope-boot-starter

1.0.0.1.RELEASE

(注:如果是SpringCloud项目,如果子项目不需要Mybatis,请移除相关的依赖)

com.mofum.scope

scope-boot-starter

1.0.0.1.RELEASE

com.mofum.scope

scope-orm-mybatis

com.mofum.scope

scope-autoconfiure

使用方法(SpringBoot版本)

SpringBoot Application 类

@SpringBootApplication

@ComponentScan(value = {

"com.mofum.scope.controller",//控制器

"com.mofum.scope.service",//本地逻辑具体业务

"com.mofum.scope.config"

})

@MapperScan("com.mofum.scope.mapper")

@EnableAutoConfiguration

@EnableAspectJAutoProxy //开启切面控制

public class Application {

public static void main(String[] args) {

ApplicationContext applicationContext = SpringApplication.run(Application.class, args);

IUserService userService = applicationContext.getBean(UserServiceImpl.class);

userService.initTable();

}

}

控制层(Controller)

@RestController

@RequestMapping("/user")

public class UserController extends ScopeController {

public static Logger logger = LoggerFactory.getLogger(UserController.class);

@Autowired

IUserService userService;

@RequestMapping("/add")

public Object addUser(User user) {

userService.addUser(user);

return "SUCCESS";

}

@RequestMapping("/query")

public Object query(UserDto userDto) {

logger.info(userDto.toString());

return userService.queryUser(userDto);

}

@RequestMapping("/scope/query")

@QueryScope

public Object scopeQuery(UserDto userDto) {

logger.info(userDto.toString());

return userService.queryUser(userDto);

}

@RequestMapping("/del")

@UpdateScope(columns = {

@ServiceColumn(value = "serviceIds")

})

public Object del(UserDto userDto) {

logger.info(userDto.toString());

return "SUCCESS";

}

}

业务层(Service)

@Service

@TableScope(columns = {

/**

* @see com.mofum.scope.controller.ScopeController 中的extractorScopes()方法

*/

@ColumnScope(type = "ScopeOne", value = "scope_one") //配置列type 是类型,scope_one是表中的列

})

public class UserServiceImpl implements IUserService {

@Autowired

UserMapper userMapper;

@Override

public void initTable() {

userMapper.createTable();

}

@Override

public void addUser(User user) {

if (user != null) {

user.setId(UUID.randomUUID().toString());

}

userMapper.insertUser(user);

}

@Override

public List queryUser(UserDto user) {

return userMapper.queryUser(user);

}

@Override

public int delete(UserDto userDto) {

return 0;

}

}

配置业务对象转换器(ScopeConvert)【必须】

public class ScopeController implements IScopeConverter {

@Override

public List convert2Scope(Object o) throws RuntimeException {

//转换业务对象为ScopeId

List scopes = new ArrayList<>();

Scope scope = new Scope();

scope.setId("1");

scope.setType("ScopeOne"); //Type和IUserService 中的注解ColumnScope要指定同一个注解才能生效

scopes.add(scope);

return scopes;

}

}

配置SQL范围提取器(ScopeExtractor)【必须】

public class ScopeController implements IScopeExtractor {

@Override

public List extends Scope> extractorScopes(Object o) throws RuntimeException {

//提取权限数据范围

//假设只有SCOPE_ONE只有权限范围1

List scopes = new ArrayList<>();

Scope scope = new Scope();

scope.setId("1");

scope.setType("ScopeOne"); //Type和IUserService 中的注解ColumnScope要指定同一个注解才能生效

scopes.add(scope);

return scopes;

}

}

配置认证器(ScopeAuthenticator)【必须】

public class ScopeController implements IScopeAuthenticator, RuntimeException>{

@Override

public boolean testAccess(List scopes) throws RuntimeException {

//取用户ID

String userId = getRequest().getParameter("userId");

//取请求URL

String url = getRequest().getRequestURI();

boolean accessFlag = false;

//验证权限逻辑

for (Scope scope : scopes) {

if (scope.getId().equals("2")) {

return true;

}

}

if (!accessFlag) {

throw new RuntimeException("Operation failed!Cause no permission!(action :" + url + ")");

}

return accessFlag;

}

public HttpServletRequest getRequest() {

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

return request;

}

public HttpServletResponse getResponse() {

HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

return response;

}

}

配置权限拦截器(Config PermissionInterceptor )【必须】

@Configuration

public class MybatisScopeAutoConfiguration {

@Autowired

private List sqlSessionFactoryList;

public MybatisScopeAutoConfiguration() {

}

@PostConstruct

public void addTestInterceptor() {

PermissionInterceptor interceptor = new PermissionInterceptor();

interceptor.setRestructureProcessor(new DruidRestructureProcessor());

Iterator var3 = this.sqlSessionFactoryList.iterator();

while (var3.hasNext()) {

SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) var3.next();

sqlSessionFactory.getConfiguration().addInterceptor(interceptor);

}

}

}

配置业务切面 (Config Scan Service Aspect)【必须】

@Component

@Aspect

public class ServiceAspectJ extends AbstractColumnAspectJ {

//配置业务切面

@Override

@Pointcut("execution(* com.mofum.scope.service..*.*(..))")

public void config() {

}

}

配置控制切面 (Config Scan Service Aspect)【必须】

@Component

@Aspect

public class ControllerAspectJ extends AbstractControllerAspectJ {

private ThrowableHandler throwableHandler;

//配置控制切面

@Override

@Pointcut("execution(* com.mofum.scope.controller..*.*(..))")

public void config() {

}

@Override

public ThrowableHandler getThrowableHandler() {

if(throwableHandler == null){

throwableHandler = new ControllerThrowableHandler();

}

return throwableHandler;

}

@Override

public void setThrowableHandler(ThrowableHandler throwableHandler) {

this.throwableHandler = throwableHandler;

}

}

配置异常处理器 (Config ErrorHandler) 【非必须】

public class ControllerThrowableHandler implements ThrowableHandler {

@Override

public void handler(Throwable throwable) throws Throwable {

if (throwable != null) {

getResponse().setCharacterEncoding("UTF-8");

getResponse().getWriter().println(throwable.getMessage());

throwable.printStackTrace();

}

}

public HttpServletRequest getRequest() {

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

return request;

}

public HttpServletResponse getResponse() {

HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

return response;

}

}

联系我们

QQ交流群:1062019634(200人)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值