提交 cf83eadb 编写于 作者: sq3536's avatar sq3536

引用修复

上级 dabd888a
server:
port: {{#if app.httpPort}}{{app.httpPort}}{{else}}8080{{/if}}
spring:
cache:
redis:
......@@ -62,6 +58,7 @@ ibiz:
### 启用Gzip压缩
server:
port: {{#if app.httpPort}}{{app.httpPort}}{{else}}8080{{/if}}
compression:
enabled: true
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
......
package {{packageName}}.core.util.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -21,6 +22,7 @@ import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
@Configuration
@ConditionalOnProperty( name = "spring.datasource.isSyncDBSchema", havingValue = "true")
public class LiquibaseConfiguration {
/**
......
package {{packageName}}.core.util.security;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.SneakyThrows;
import cn.ibizlab.util.annotation.DEField;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.enums.DEPredefinedFieldType;
import cn.ibizlab.util.filter.QueryWrapperContext;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.function.Consumer;
/**
* spring security 权限管理类
* 重写权限控制方法
*/
@Component
public class AuthPermissionEvaluator implements PermissionEvaluator {
@Value("${ibiz.enablePermissionValid:false}")
boolean enablePermissionValid; //是否开启权限校验
/**
* 服务接口鉴权
* @param authentication 用户
* @param entity 实体
* @param action 操作
* @return
*/
@Override
@SneakyThrows
public boolean hasPermission(Authentication authentication, Object entity, Object action) {
if(!enablePermissionValid){
return true;
}
Object principal = authentication.getPrincipal();
if(ObjectUtils.isEmpty(principal)){
return false;
}
AuthenticationUser authenticationUser= (AuthenticationUser) authentication.getPrincipal();
if(authenticationUser.getSuperuser()==1){
return true;
}
String strAction=String.valueOf(action);
Set<String> userAuthorities = getAuthorities(authentication,strAction);
if(userAuthorities.size()==0){
return false;
}
if(isAllData(strAction,userAuthorities)){
return true;
}
if(entity instanceof ArrayList){
List<EntityBase> entities= (List<EntityBase>) entity;
for(EntityBase entityBase: entities){
boolean result=actionValid(entityBase, strAction ,userAuthorities,authenticationUser);
if(!result){
return false;
}
}
}
else if (entity instanceof QueryWrapperContext){
QueryWrapperContext queryWrapperContext= (QueryWrapperContext) entity;
setPermissionCondToSearchContext(getEntity(queryWrapperContext),queryWrapperContext,userAuthorities,authenticationUser);
}
else{
EntityBase entityBase= (EntityBase) entity;
return actionValid(entityBase , strAction ,userAuthorities,authenticationUser);
}
return true;
}
/**
* 获取实体信息
* @param qc
* @return
*/
@SneakyThrows
private EntityBase getEntity(QueryWrapperContext qc){
EntityBase entity=null;
Type type =qc.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType){
ParameterizedType parameterizedType= (ParameterizedType) qc.getClass().getGenericSuperclass();
Type [] typeArr= parameterizedType.getActualTypeArguments();
if(typeArr.length>0){
Class<EntityBase> entityClass = (Class) typeArr[0];
return entityClass.newInstance();
}
}
return entity;
}
/**
* 在searchContext中拼接权限条件
* @param entity 实体
* @param qc 查询上下文
* @param userAuthorities 用户权限
* @param authenticationUser 当前用户
*/
@SneakyThrows
private void setPermissionCondToSearchContext(EntityBase entity, QueryWrapperContext qc , Set<String> userAuthorities ,AuthenticationUser authenticationUser){
if(entity==null){
return ;
}
Map<String,String> permissionField=getPermissionField(entity);//获取组织、部门预置属性
String orgField=permissionField.get("orgfield");
String orgDeptField=permissionField.get("orgsecfield");
String createManField=permissionField.get("createmanfield");
Map<String, Set<String>> userInfo = authenticationUser.getOrgInfo();
Set<String> orgParent = userInfo.get("parentorg");
Set<String> orgChild = userInfo.get("suborg");
Set<String> orgDeptParent = userInfo.get("parentdept");
Set<String> orgDeptChild = userInfo.get("subdept");
Set<String> userOrg = new HashSet<>();
Set<String> userOrgDept = new HashSet<>();
Set<String> userCreateMan = new HashSet<>();
for(String authority:userAuthorities){
if(authority.endsWith("curorg")){ //本单位
userOrg.add(authenticationUser.getOrgid());
}
else if(authority.endsWith("porg")){//上级单位
userOrg.addAll(orgParent);
}
else if(authority.endsWith("sorg")){//下级单位
userOrg.addAll(orgChild);
}
else if(authority.endsWith("curorgdept")){//本部门
userOrgDept.add(authenticationUser.getMdeptid());
}
else if(authority.endsWith("porgdept")){//上级部门
userOrgDept.addAll(orgDeptParent);
}
else if(authority.endsWith("sorgdept")){//下级部门
userOrgDept.addAll(orgDeptChild);
}
else if (authority.endsWith("createman")){
userCreateMan.add(authority);
}
}
if(userOrg.size()==0 && userOrgDept.size()==0 && userCreateMan.size()==0){
qc.getSelectCond().apply("1<>1");
}
else{
Consumer<QueryWrapper> consumer = qw -> {
if(userOrg.size()>0){
Consumer<QueryWrapper> org = orgQw -> {
orgQw.in(orgField,userOrg);
};
qw.or(org);
}
if(userOrgDept.size()>0){
Consumer<QueryWrapper> dept = deptQw -> {
deptQw.in(orgDeptField,userOrgDept);
};
qw.or(dept);
}
if(userCreateMan.size()>0){
Consumer<QueryWrapper> createMan = createManQw -> {
createManQw.eq(createManField,authenticationUser.getUserid());
};
qw.or(createMan);
}
};
qc.getSelectCond().and(consumer);
}
}
@Override
public boolean hasPermission(Authentication authentication, Serializable id, String action, Object params) {
return true;
}
/**
* 获取用户权限资源
* @param authentication
* @param action
* @return
*/
private Set<String> getAuthorities(Authentication authentication , String action){
Collection authorities=authentication.getAuthorities();
Set<String> userAuthorities = new HashSet();
Iterator it = authorities.iterator();
while(it.hasNext()) {
GrantedAuthority authority = (GrantedAuthority)it.next();
if(authority.getAuthority().contains(action)){
userAuthorities.add(authority.getAuthority());
}
}
return userAuthorities;
}
/**
* 是否为全部数据
* @param action
* @param entityDataRange
* @return
*/
private boolean isAllData(String action , Set<String> entityDataRange) {
for(String dataRange : entityDataRange ){
if(dataRange.endsWith(String.format("%s-all",action))){
return true;
}
}
return false;
}
/**
* 实体行为权限校验
* @param entity
* @param userAuthorities
* @return
*/
private boolean actionValid(EntityBase entity, String action , Set<String> userAuthorities ,AuthenticationUser authenticationUser){
Map<String,String> permissionField=getPermissionField(entity);//获取组织、部门预置属性
String orgField=permissionField.get("orgfield");
String orgDeptField=permissionField.get("orgsecfield");
String createManField=permissionField.get("createmanfield");
Map<String, Set<String>> userInfo = authenticationUser.getOrgInfo();
Set<String> orgParent = userInfo.get("parentorg");
Set<String> orgChild = userInfo.get("suborg");
Set<String> orgDeptParent = userInfo.get("parentdept");
Set<String> orgDeptChild = userInfo.get("subdept");
Object orgFieldValue=entity.get(orgField);
Object orgDeptFieldValue=entity.get(orgDeptField);
Object crateManFieldValue=entity.get(createManField);
Set<String> userOrg = new HashSet<>();
Set<String> userOrgDept = new HashSet<>();
for(String authority:userAuthorities){
if(authority.endsWith("curorg")){ //本单位
userOrg.add(authenticationUser.getOrgid());
}
else if(authority.endsWith("porg")){//上级单位
userOrg.addAll(orgParent);
}
else if(authority.endsWith("sorg")){//下级单位
userOrg.addAll(orgChild);
}
else if(authority.endsWith("curorgdept")){//本部门
userOrgDept.add(authenticationUser.getMdeptid());
}
else if(authority.endsWith("porgdept")){//上级部门
userOrgDept.addAll(orgDeptParent);
}
else if(authority.endsWith("sorgdept")){//下级部门
userOrgDept.addAll(orgDeptChild);
}
}
if(action.endsWith("Create") || action.endsWith("Save")){
if(!ObjectUtils.isEmpty(orgFieldValue) && !userOrg.contains(orgFieldValue)){
return false;
}
if(!ObjectUtils.isEmpty(orgDeptFieldValue) && !userOrgDept.contains(orgDeptFieldValue)){
return false;
}
if(!ObjectUtils.isEmpty(crateManFieldValue) && !authenticationUser.getUserid().equals(crateManFieldValue)){
return false;
}
return true;
}
else{
if(!ObjectUtils.isEmpty(orgFieldValue) && userOrg.contains(orgFieldValue)){
return true;
}
if(!ObjectUtils.isEmpty(orgDeptFieldValue) && userOrgDept.contains(orgDeptFieldValue)){
return true;
}
if(!ObjectUtils.isEmpty(crateManFieldValue) && authenticationUser.getUserid().equals(crateManFieldValue)){
return true;
}
return false;
}
}
/**
* 获取实体权限字段 orgid/orgsecid
* @param entityBase
* @return
*/
private Map<String,String> getPermissionField(EntityBase entityBase){
Map<String,String> permissionFiled=new HashMap<>();
String orgField="orgid"; //组织属性
String orgDeptField="orgsectorid"; //部门属性
String createManField="createman"; //创建人属性
DEFieldCacheMap.getFieldMap(entityBase.getClass().getName());
Map <String, DEField> preFields= DEFieldCacheMap.getDEFields(entityBase.getClass()); //从缓存中获取当前类预置属性
for (Map.Entry<String,DEField> entry : preFields.entrySet()){
DEField fieldAnnotation=entry.getValue();//获取注解值
String fieldName=fieldAnnotation.name();//获取注解字段
DEPredefinedFieldType prefieldType=fieldAnnotation.preType();
if(!StringUtils.isEmpty(fieldName)){
//用户配置系统预置属性-组织机构标识
if(prefieldType==prefieldType.ORGID){
orgField=fieldName;
}
//用户配置系统预置属性-部门标识
if(prefieldType==prefieldType.ORGSECTORID){
orgDeptField=fieldName;
}
//用户配置系统预置属性-部门标识
if(prefieldType==prefieldType.CREATEMAN){
createManField=fieldName;
}
}
}
permissionFiled.put("orgfield",orgField);
permissionFiled.put("orgsecfield",orgDeptField);
permissionFiled.put("createmanfield",createManField);
return permissionFiled;
}
}
\ No newline at end of file
......@@ -43,26 +43,6 @@ spring:
isSyncDBSchema: false
defaultSchema: {{projectName}}
{{#if system.enableDS}}
conf: classpath:liquibase/master.xml
filters: stat,wall,log4j2
#配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
{{else}}
dynamic:
druid: #以下是全局默认值,可以全局更改
filters: stat,log4j2
......@@ -100,6 +80,26 @@ spring:
conf: classpath:liquibase/master.xml
isSyncDBSchema: ${spring.datasource.isSyncDBSchema}
defaultSchema: ${spring.datasource.defaultSchema}
{{else}}
conf: classpath:liquibase/master.xml
filters: stat,wall,log4j2
#配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
{{/if}}
#Mybatis-plus配置
......
......@@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<version>2.2.5.RELEASE</version>
</parent>
<properties>
......@@ -25,22 +25,22 @@
<spring-cloud-security.version>2.1.1.RELEASE</spring-cloud-security.version>
<!-- openfeign -->
<spring-cloud-openfeign.version>2.2.1.RELEASE</spring-cloud-openfeign.version>
<spring-cloud-openfeign.version>2.2.5.RELEASE</spring-cloud-openfeign.version>
<!-- Zuul网关 -->
<spring-cloud-starter-netflix-zuul.version>2.2.1.RELEASE</spring-cloud-starter-netflix-zuul.version>
<spring-cloud-starter-netflix-zuul.version>2.2.5.RELEASE</spring-cloud-starter-netflix-zuul.version>
<!-- Spring Cloud Alibaba(2.2.x.RELEASE) & Spring Cloud(Spring Cloud Greenwich) & Spring Boot(2.2.x.RELEASE) compatibility -->
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
<!-- eureka微服务注册中心 -->
<eureka-client.version>2.2.1.RELEASE</eureka-client.version>
<eureka-client.version>2.2.5.RELEASE</eureka-client.version>
<!--Java Web Token-->
<jsonwebtoken-jjwt.version>0.9.1</jsonwebtoken-jjwt.version>
<!--caffeine缓存-->
<caffeine-cache.version>2.6.0</caffeine-cache.version>
<caffeine.version>2.8.1</caffeine.version>
<!--反序列化工具-->
<kryo.version>4.0.2</kryo.version>
......@@ -80,24 +80,24 @@
<baomidou-jobs.version>1.0.3</baomidou-jobs.version>
<!-- 阿里sentinel熔断器 -->
<alibaba-sentinel.version>2.1.1.RELEASE</alibaba-sentinel.version>
<alibaba-sentinel.version>2.2.1.RELEASE</alibaba-sentinel.version>
<!-- 阿里seata分布式事务 -->
<alibaba-seata.version>1.3.0</alibaba-seata.version>
<oracle.version>19.8.0.0</oracle.version>
<ojdbc.version>19.8.0.0</ojdbc.version>
<postgresql.version>42.2.6</postgresql.version>
<postgresql.version>42.2.10</postgresql.version>
<mysql.version>8.0.18</mysql.version>
<mysql.version>8.0.19</mysql.version>
<rocketmq.version>4.7.0</rocketmq.version>
<flowable-modeler.version>6.4.2</flowable-modeler.version>
<ibizlab-common.version>1.0.2</ibizlab-common.version>
<ibizlab-common.version>1.0.3</ibizlab-common.version>
<ibizlab-util.version>1.0.2</ibizlab-util.version>
<ibizlab-util.version>1.0.3</ibizlab-util.version>
</properties>
......@@ -154,7 +154,7 @@
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine-cache.version}</version>
<version>${caffeine.version}</version>
</dependency>
<dependency>
......@@ -301,12 +301,12 @@
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>${oracle.version}</version>
<version>${ojdbc.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.database.nls</groupId>
<artifactId>orai18n</artifactId>
<version>${oracle.version}</version>
<version>${ojdbc.version}</version>
</dependency>
<!-- PostgreSQL驱动包 -->
<dependency>
......@@ -318,7 +318,13 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<version>${mysql.version}</version>
<exclusions>
<exclusion>
<artifactId>protobuf-java</artifactId>
<groupId>com.google.protobuf</groupId>
</exclusion>
</exclusions>
</dependency>
......
......@@ -27,6 +27,11 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
......
......@@ -59,7 +59,7 @@ public class SwaggerConfiguration {
.build()
)
.select()
.apis(RequestHandlerSelectors.basePackage("{{packageName}}.{{api.codeName}}"))
.apis(RequestHandlerSelectors.basePackage("{{packageName}}.{{lowerCase api.codeName}}"))
.paths(PathSelectors.any())
.build();
}
......
......@@ -25,11 +25,11 @@ import java.util.List;
@EnableTransactionManagement
@ComponentScan(basePackages = {"{{packageName}}","cn.ibizlab.util"}
// ,excludeFilters={
// @ComponentScan.Filter(type= org.springframework.context.annotation.FilterType.REGEX,pattern="{{packageName}}.${item.codeName?lower_case}.rest.xxx"),
// @ComponentScan.Filter(type= org.springframework.context.annotation.FilterType.REGEX,pattern="{{packageName}}.{{lowerCase api.codeName}}.rest.xxx"),
// }
)
@EnableMongoRepositories(basePackages = {"{{packageName}}"})
@MapperScan("{{packageName}}.*.mapper")
@MapperScan({"{{packageName}}.*.mapper","cn.ibizlab.util.mapper" })
@SpringBootApplication(exclude = {
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class,
{{#unless system.enableMongo}}
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册