查询时根据权限更改sql
import java.lang.reflect.Method; import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.web.context.ContextLoader;
/**
*
* We construct data security layer,Generally speaking:
* When the wms start, we detect the security metadata and put it into WMSSecurityContext
* A request arrive,if there is an Annotation EnbableDataSewcurity upon the method,we register(mistake) method info into WMSSecurityContext
* Before data access,we will check if the "data access session" need in an "security environment".
* If yes,we alternative sql.then post to db.
* please see detail information about alternative sql in class DataPermissionSqlUtil
*
* */
public class DataPermissionBeforeAdvice implements MethodBeforeAdvice { //logger for class DataPermissionBeforeAdvice
private static final Logger logger = Logger.getLogger(DataPermissionBeforeAdvice.class); @Override
public void before(Method method, Object[] args, Object target) throws Throwable {
boolean shouldExecuteDataSecurity = checkIfNeedExecuteDataSecurity();
if (shouldExecuteDataSecurity) {
executeDataSecurity(method, args, target, shouldExecuteDataSecurity);
}
} /**
* check if the "session" need an security context.
* */
private boolean checkIfNeedExecuteDataSecurity() {
boolean shouldExecuteDataSecurity = false ;
String dataSecurityMethodSignature = WMSSecurityContext.getDataSecurityMethodSignature().get();
if (dataSecurityMethodSignature != null) { // 确定调用方法拥有 @EnableDataSecurity注解标识
// web.xml文件中已经启用数据权限
String enableDataSecurity = ContextLoader.getCurrentWebApplicationContext().getServletContext().getInitParameter("EnableDataSecurity");
if (enableDataSecurity != null && "true".equals(enableDataSecurity)) {
shouldExecuteDataSecurity = true;
}
}
return shouldExecuteDataSecurity;
} /**
* retrieve security metadata ,and alternative sql(s).
* */
@SuppressWarnings("rawtypes")
private void executeDataSecurity(Method method, Object[] args,
Object target, boolean shouldExecuteDataSecurity) throws Throwable {
if (target instanceof JdbcOperations) {
if (logger.isDebugEnabled()) {
logger.debug("exeute data security begin.");
}
// do alternative sql operation
if (shouldExecuteDataSecurity) {
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class paramterType = parameterTypes[i];
if ("String".equals(paramterType.getSimpleName())) {
String sql = (String) args[i];
String sqlByDataPermission = DataPermissionSqlUtil.alternateSqlByDataPermission(sql);
if (logger.isDebugEnabled()) {
logger.debug("sql after data permission: " + sqlByDataPermission);
}
args[i] = sqlByDataPermission;
} else if ("String[]".equals(paramterType.getSimpleName())) {
String[] sqls = (String[]) args[i];
for (int j = 0; j < sqls.length; j++) {
String sql = sqls[j];
String sqlByDataPermission = DataPermissionSqlUtil.alternateSqlByDataPermission(sql);
sqls[j] = sqlByDataPermission;
}
args[i] = sqls;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("exeute data security end.");
}
}
} }
import java.io.StringReader;
import java.util.List; import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.TablesNamesFinder; import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger; /**
* Handy class for alternative SQL with data authority and user context
*/
public class DataPermissionSqlUtil { //logger for class DataPermissionSqlUtil
private static final Logger logger =
Logger.getLogger(DataPermissionSqlUtil.class); private static CCJSqlParserManager pm = new CCJSqlParserManager(); /**
* calculate subquery by table name
* */
public static String alternateSqlByDataPermission(String sql) throws Exception { if (logger.isDebugEnabled()) {
logger.debug("alternateSqlByDataPermission begin...");
} List<String> tableNames = getTableNames(sql);
// if sql is not SELECT type
// return sql directly
if (null == tableNames) {
return sql;
}
for (String tablename : tableNames) {
// calculate alternative SQL
String subquery = getSubqueryByTableName(tablename);
if (logger.isDebugEnabled()) {
logger.debug("table name is : " + tablename + " subquery is : " + subquery);
}
// replace table name to subquery
sql = sql.replaceAll(tablename, subquery);
// 只替换第一个表名(主表),关联表名 不替换
break;
}
return sql;
} /**
* detect table names from given table
* ATTENTION : WE WILL SKIP SCALAR SUBQUERY IN PROJECTION CLAUSE
* */
private static List<String> getTableNames(String sql) throws Exception {
List<String> tablenames = null;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
Statement statement = pm.parse(new StringReader(sql));
if (statement instanceof Select) {
tablenames = tablesNamesFinder.getTableList((Select) statement);
} else if (statement instanceof Update) {
return null;
} else if (statement instanceof Delete) {
return null;
} else if (statement instanceof Replace) {
return null;
} else if (statement instanceof Insert) {
return null;
}
return tablenames;
} private static String getSubqueryByTableName(String tableName) throws Exception {
String subquery = null;
String relatedFromClause = processFromConstriant(tableName); // 拼接关联表查询字段 控制权限
String experiyWhereClause = processExperiyConstriant(tableName); // 拼接Status字段控制启用 禁用,指定状态字段
String domainWhereClause = processDomainConstriant(tableName); // 根据员工登录 控制只能看到当前登录机构的数据,指定机构字段
String dataPermissionWhereClause = processDataPermissionConstriant(tableName); // 数据权限控制 if(StringUtils.isEmpty(experiyWhereClause) && StringUtils.isEmpty(domainWhereClause) && StringUtils.isEmpty(dataPermissionWhereClause)) {
return tableName;
} else {
StringBuilder querySb = new StringBuilder()
.append(" ( ").append(SqlConstants.SQL_SELECT).append(" ").append(DataSecurityHelper.getMainTableAlias(tableName)).append(" * ")
.append(SqlConstants.SQL_FROM).append(" ").append(tableName).append(" ");
if(StringUtils.isNotBlank(relatedFromClause)) {
querySb.append(relatedFromClause).append(" ");
}
querySb.append(SqlConstants.SQL_WHERE).append(" ");
if(StringUtils.isNotBlank(experiyWhereClause)) {
querySb.append(experiyWhereClause).append(" ").append(SqlConstants.SQL_AND);
}
if(StringUtils.isNotBlank(domainWhereClause)) {
querySb.append(domainWhereClause).append(" ").append(SqlConstants.SQL_AND);
}
if(StringUtils.isNotBlank(dataPermissionWhereClause)) {
querySb.append(dataPermissionWhereClause).append(" ").append(SqlConstants.SQL_AND);
}
querySb = StringUtil.deleteLastSequence(querySb,SqlConstants.SQL_AND);
querySb.append(" ) ");
subquery = querySb.toString();
}
return subquery;
} /**
* filter related from table column data
* lifeng
* */
private static String processFromConstriant(String tableName) {
String relatedFromClause = DataSecurityHelper.buildRelatedConstriantSql(tableName);
return relatedFromClause;
} /**
* filter expiry data
* */
private static String processExperiyConstriant(String tableName) {
String experiyWhereClause = DataSecurityHelper.buildExpiryConstriantSql(tableName);
return experiyWhereClause;
} /**
* filter domain data
* */
private static String processDomainConstriant(String tableName) {
String domainWhereClause = DataSecurityHelper.buildDomainConstriantSql(tableName);
return domainWhereClause;
} /**
* filter permission data
* */
private static String processDataPermissionConstriant(String tableName) {
String dataPermissionWhereClause = DataSecurityHelper.buildDataAuthorityConstriantSql(tableName);
return dataPermissionWhereClause;
} }
applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd"> <mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.yundaex.wms" /> <!-- Base package to scan the mongo repositories, where we create de DAOS to access data and domain objects -->
<mongo:repositories base-package="com.yundaex.wms.security.mongo" /> <bean id="dataPermissionBeforeAdvice" class="com.yundaex.common.security.advice.DataPermissionBeforeAdvice" /> <aop:config proxy-target-class="true">
<aop:pointcut expression="execution(public * org.springframework.jdbc.core.JdbcTemplate.*(..)) and !execution(public * org.springframework.jdbc.core.JdbcTemplate.queryForList(*))" id="jdbcTemplatePointcut"/>
<aop:advisor advice-ref="dataPermissionBeforeAdvice" pointcut-ref="jdbcTemplatePointcut"/>
</aop:config> <bean id="mongoRoleDao" class="com.yundaex.wms.security.mongo.impl.MongoRoleDaoImpl">
</bean> <bean id="mongoFunctionAuthorityDao" class="com.yundaex.wms.security.mongo.impl.MongoFunctionAuthorityDaoImpl">
</bean> <bean id="mongoUserDao" class="com.yundaex.wms.security.mongo.impl.MongoUserDaoImpl"></bean> </beans>
web.xml
<!-- Enable data security -->
<context-param>
<param-name>EnableDataSecurity</param-name>
<param-value>true</param-value>
</context-param>
查询时根据权限更改sql的更多相关文章
- IN 查询时出现ORA-01795:列表中的最大表达式数为1000解决方法
问题描写叙述: SQL进行IN查询时出现:java.sql.SQLException: ORA-01795: 列表中的最大表达式数为 1000 解决的方法: 问题原因是:SQL进行IN查询时.IN中的 ...
- sql 关于查询时 出现的 从数据类型 varchar 转换为 numeric 时出错 的解决方法。
出现这种问题 一般是查询时出现了 varchar 转 numeric 时出了错 或varchar字段运算造成的 解决方法: 让不能转的数不转换就可以了 sql的函数有个isNumeric(参数) 用 ...
- 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句
如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true) ...
- PL/SQL Developer 使用中文条件查询时无数据的解决方法
PL/SQL Developer 使用中文条件查询时无数据,这是由于字符集的不一致导致的. 执行以下sql命令:select userenv('language') from dual; 显示:SIM ...
- oracle中使用sql查询时字段为空则赋值默认
转至:http://www.th7.cn/db/Oracle/201501/86125.shtml oracle 通过 nvl( )函数sql 查询时为 空值 赋默认值 oracle 函数介绍之nvl ...
- 警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱
警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱 以下文章来源:https://blog.csdn.net/defonds/article/details/4 ...
- [转]关于oracle sql语句查询时表名和字段名要加双引号的问题
oracle初学者一般会遇到这个问题. 用navicat可视化创建了表,可是就是不能查到! 后来发现②语句可以查询到 ①select * from user; 但是,我们如果给user加上双引 ...
- SQL字段类型bit 查询时注意
sql 查询时 字段=1 或 字段=0 c# 里也是
- SQL Server查询时添加一列连续的自增列
SQL Server查询时添加一列连续的自增列 在SQL Server数据库中表信息会用到Identity关键字来设置自增列.但是当有数据被删除的话,自增列就不连续了.如果想查询出这个表的信息,并添加 ...
随机推荐
- ACM学习历程—HDU5637 Transform(数论 && 最短路)
题目链接:http://codeforces.com/problemset/problem/590/A 题目大意是给两种操作,然后给你一个s,一个t,求s至少需要多少次操作到t. 考虑到第一种操作是将 ...
- noip寻找道路
题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条 ...
- 分立元件封装尺寸及PCB板材工艺与设计实例
分立元件封装尺寸 inch mm (L)mm (w)mm (t)mm (a)mm (b)mm 0201 0603 0.6±0.05 0.30±0.05 0.23±0.05 0.10±0.05 0.60 ...
- [转]HTTP中cache-control的应用及说明
网页的缓存是由http消息头中的“Cache-control”来控制的,常见的取值有private.no-cache.max-age.must-revalidate等,默认为private.其作用根据 ...
- jquery给select赋值
项目中用到通过ajax请求数据然后给select赋值,由于经常遇到类似的代码,在这里把整个过程记录一下. 首选发出ajax请求如下: <script type="text/javasc ...
- UE3代码阅读需知
转自:http://www.cnblogs.com/hmxp8/archive/2012/02/21/2361211.html 掌握一款庞大的引擎,要一下子掌握真的很难,慢慢地从Editor,Scri ...
- java继承示例
package day07; class Fu { int num = 5; } class Zi extends Fu { int num =7; void show() { int num =9; ...
- Java探索之旅(17)——多线程(1)
1.多线程 1.1线程 线程是程序运行的基本执行单元.指的是一段相对独立的代码,执行指定的计算或操作.多操作系统执行一个程序时会在系统中建立一个进程,而在这个进程中,必须至少建立一个线程(这个线程被 ...
- 【总结整理】JQuery基础学习---样式篇
进入官方网站获取最新的版本 http://jquery.com/download/ 中文 https://www.jquery123.com/ <!--JQuery:轻量级的JavaScr ...
- Angular10 组件之间的通讯
1 父组件和子组件之间的通讯 2 利用中间组件实现两个组件之间的通讯 3 利用服务实现两个组件之间的通讯 2017年8月26日20:09:13 待更新... 1 组件之间的关系图 1.1 父子关系 1 ...