Master Dynamic Data Permissions in Spring Boot with Easy-Data-Scope
This tutorial walks through setting up the easy-data-scope library in a Spring Boot project, configuring the database and dependencies, defining DataScopeInfo, using the @DataScope annotation, and demonstrating various permission scenarios such as filtering by ID, age, merging conditions, and custom templates.
Introduction
easy-data-scopeis a data‑permission project that injects SQL dynamically, supporting MyBatis, MyBatis‑plus, and MyBatis‑flex. It works via annotations without complex configuration.
Basic Project Setup
1. Database: a simple user table (see image).
Only view records with id = 1 Only view records with age = 111 Only view records with age = 222 View records with age = 111 or age = 222 2. Add basic dependencies (MyBatis‑plus, MyBatis XML):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>3. Core dependency:
<dependency>
<groupId>cn.zlinchuan</groupId>
<artifactId>ds-mybatis</artifactId>
<version>1.0.1</version>
</dependency>4. Main class:
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class);
}
}5. application.yml configuration:
server:
port: 8001
# DataSource Config
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: url
username: name
password: password
mybatis:
mapper-locations: classpath:mapper/*.xml
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImplUsing easy-data-scope
Implement the core interface DataScopeFindRule and let Spring manage it.
DataScopeInfo
easy-data-scopebuilds SQL based on the list of DataScopeInfo returned by find().
@DataScope annotation
Place on methods that need data‑permission interception. Attributes include keys, template, merge, logical, and flag.
public @interface DataScope {
/** Keys used to retrieve DataScopeInfo */
String[] keys();
/** Template for building SQL when multiple keys are used */
String template() default "";
/** Whether to merge permissions with the same table/column */
boolean merge() default false;
/** Logical operator (WHERE, AND, OR, etc.) */
String logical() default SqlConsts.AND;
/** Whether to use the data‑scope flag placeholder */
boolean flag() default false;
}Implementing DataScopeFindRule
@Override
public List<DataScopeInfo> find(String[] key) {
UserSessionInfo userSession = UserSessionContext.getUserSession();
if (userSession != null) {
QueryWrapper<AuthDatascopeEntity> idQueryWrapper = new QueryWrapper<>();
idQueryWrapper.in("id", userSession.getDataScopeIds());
idQueryWrapper.in("datascope_key", key);
List<AuthDatascopeEntity> authDatascopes = authDataSocpeMapper.selectList(idQueryWrapper);
List<DataScopeInfo> dataScopeInfos = new ArrayList<>(authDatascopes.size());
for (AuthDatascopeEntity authDatascope : authDatascopes) {
DataScopeInfo dataScopeInfo = new DataScopeInfo();
dataScopeInfo.setKey(authDatascope.getDatascopeKey());
dataScopeInfo.setOperator(authDatascope.getDatascopeOpName());
dataScopeInfo.setTableName(authDatascope.getDatascopeTbName());
dataScopeInfo.setColumnName(authDatascope.getDatascopeColName());
dataScopeInfo.setSql(authDatascope.getDatascopeSql());
dataScopeInfo.setValue(authDatascope.getDatascopeValue());
dataScopeInfo.setSort(authDatascope.getDatascopeSort());
dataScopeInfos.add(dataScopeInfo);
}
return dataScopeInfos;
}
return Collections.emptyList();
}Creating the data‑permission table
CREATE TABLE auth_datascope (
id int AUTO_INCREMENT PRIMARY KEY,
datascope_key varchar(200) NULL COMMENT '数据权限标识',
datascope_name varchar(200) NULL COMMENT '数据权限名称',
datascope_tb_name varchar(500) NULL COMMENT '数据权限表别名',
datascope_col_name varchar(500) NULL COMMENT '数据权限字段名',
datascope_op_name varchar(10) NULL COMMENT '数据权限操作符',
datascope_sql varchar(5000) NULL COMMENT '数据权限sql',
datascope_value varchar(200) NULL COMMENT '数据权限值',
datascope_sort int NULL COMMENT '数据权限排序',
datascope_des varchar(500) NULL COMMENT '数据权限描述'
) COMMENT '数据权限表';Examples
Only id = 1:
@DataScope(keys = "USER_LIST_ID", logical = SqlConsts.WHERE)
public List<UserEntity> getAll() {
return userMapper.selectList(null);
}Generated SQL:
SELECT id,username,age FROM user WHERE ( user.id = 1 )Only age = 111:
@DataScope(keys = "USER_LIST_AGE111", logical = SqlConsts.WHERE)
public List<UserEntity> getAll2() {
return userMapper.selectList(null);
} SELECT id,username,age FROM user WHERE ( user.age = 111 )Only age = 222:
@DataScope(keys = "USER_LIST_AGE222", logical = SqlConsts.WHERE)
public List<UserEntity> getAll3() {
return userMapper.selectList(null);
} SELECT id,username,age FROM user WHERE ( user.age = 222 )Merge ages 111 and 222 (using merge = true):
@DataScope(keys = {"USER_LIST_AGE111","USER_LIST_AGE222"}, merge = true, logical = SqlConsts.WHERE)
public List<UserEntity> getAll4() {
return userMapper.selectList(null);
} SELECT id,username,age FROM user WHERE ( user.age IN (111,222) )Using flag attribute in mapper XML:
@DataScope(keys = {"USER_LIST_AGE111","USER_LIST_AGE222"}, merge = true, flag = true)
List<UserEntity> getAll5();
/* Mapper XML */
<select id="getAll5" resultType="cn.zlinchuan.entity.UserEntity">
select * from (select * from user where {{_DATA_SCOPE_FLAG}}) t where 1 = 1
</select>Using template attribute to customize SQL:
@DataScope(keys = {"USER_LIST_AGE111","USER_LIST_AGE222"}, flag = true, template = "{{USER_LIST_AGE111}} OR {{USER_LIST_AGE222}}")
List<UserEntity> getAll6();
/* Mapper XML */
<select id="getAll6" resultType="cn.zlinchuan.entity.UserEntity">
select * from (select * from user where {{_DATA_SCOPE_FLAG}}) t where 1 = 1
</select>Project Source Code
GitHub repository: https://github.com/zoulinchuan/easy-data-scope
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
