1111import com .tinyengine .it .dynamic .dto .DynamicUpdate ;
1212import com .tinyengine .it .model .dto .ParametersDto ;
1313import com .tinyengine .it .model .entity .Model ;
14- import lombok .RequiredArgsConstructor ;
1514import lombok .extern .slf4j .Slf4j ;
1615
16+ import com .tinyengine .it .common .utils .SqlIdentifierValidator ;
17+ import com .tinyengine .it .service .material .ModelService ;
18+ import org .springframework .context .annotation .Lazy ;
1719import org .springframework .jdbc .core .JdbcTemplate ;
1820import org .springframework .jdbc .core .PreparedStatementCreator ;
1921import org .springframework .jdbc .core .namedparam .NamedParameterJdbcTemplate ;
3133
3234@ Service
3335@ Slf4j
34- @ RequiredArgsConstructor
3536public class DynamicModelService {
3637
38+ private static final Set <String > SYSTEM_FIELDS = Set .of (
39+ "id" , "created_at" , "updated_at" , "deleted_at" , "created_by" , "updated_by"
40+ );
41+
3742 private final JdbcTemplate jdbcTemplate ;
3843 private final NamedParameterJdbcTemplate namedParameterJdbcTemplate ;
3944 private final LoginUserContext loginUserContext ;
45+ private final ModelService modelService ;
46+
47+ public DynamicModelService (JdbcTemplate jdbcTemplate ,
48+ NamedParameterJdbcTemplate namedParameterJdbcTemplate ,
49+ LoginUserContext loginUserContext ,
50+ @ Lazy ModelService modelService ) {
51+ this .jdbcTemplate = jdbcTemplate ;
52+ this .namedParameterJdbcTemplate = namedParameterJdbcTemplate ;
53+ this .loginUserContext = loginUserContext ;
54+ this .modelService = modelService ;
55+ }
4056
4157
4258 /**
@@ -182,6 +198,17 @@ public List<Map<String, Object>> dynamicQuery(String tableName,
182198 String orderBy ,
183199 Integer limit ) {
184200
201+ SqlIdentifierValidator .validate (tableName );
202+ SqlIdentifierValidator .validateAll (fields );
203+ if (conditions != null && !conditions .isEmpty ()) {
204+ for (String key : conditions .keySet ()) {
205+ SqlIdentifierValidator .validate (key );
206+ }
207+ }
208+ if (orderBy != null && !orderBy .isEmpty ()) {
209+ SqlIdentifierValidator .validate (orderBy .replaceAll ("(?i)\\ s+(ASC|DESC)$" , "" ));
210+ }
211+
185212 // 1. 构建SQL
186213 StringBuilder sql = new StringBuilder ("SELECT " );
187214
@@ -267,18 +294,19 @@ public Long count(String tableName, Map<String, Object> conditions) {
267294 * 分页查询
268295 */
269296 public Map <String , Object > queryWithPage (DynamicQuery dto ) {
270- String tableName = getTableName ( dto .getNameEn ());
297+ String tableName = getTableName (dto .getNameEn ());
271298 List <String > fields = dto .getFields ();
272299 Map <String , Object > conditions = dto .getParams ();
273300 String orderBy = dto .getOrderBy ();
274301 Integer pageNum = dto .getCurrentPage ();
275302 Integer pageSize = dto .getPageSize ();
276303
304+ validateQueryFields (dto );
305+
277306 // 计算分页
278307 Integer limit = null ;
279308 if (pageNum != null && pageSize != null ) {
280309 limit = pageSize ;
281- // 如果需要偏移量,可以在这里处理
282310 }
283311
284312 // 执行查询
@@ -292,6 +320,60 @@ public Map<String, Object> queryWithPage(DynamicQuery dto) {
292320
293321 return result ;
294322 }
323+
324+ private Set <String > getAllowedFields (String nameEn ) {
325+ List <Model > modelList = modelService .getModelByEnName (nameEn );
326+ if (modelList == null || modelList .isEmpty ()) {
327+ return Collections .emptySet ();
328+ }
329+ Model model = modelList .get (0 );
330+ Set <String > allowed = new HashSet <>(SYSTEM_FIELDS );
331+ if (model .getParameters () != null ) {
332+ for (Object param : model .getParameters ()) {
333+ String prop = extractProp (param );
334+ if (prop != null ) {
335+ allowed .add (prop );
336+ }
337+ }
338+ }
339+ return allowed ;
340+ }
341+
342+ @ SuppressWarnings ("unchecked" )
343+ private String extractProp (Object param ) {
344+ if (param instanceof ParametersDto ) {
345+ return ((ParametersDto ) param ).getProp ();
346+ }
347+ if (param instanceof Map ) {
348+ Object value = ((Map <String , Object >) param ).get ("prop" );
349+ return value != null ? value .toString () : null ;
350+ }
351+ return null ;
352+ }
353+
354+ private void validateQueryFields (DynamicQuery dto ) {
355+ Set <String > allowedFields = getAllowedFields (dto .getNameEn ());
356+
357+ if (dto .getFields () != null && !dto .getFields ().isEmpty ()) {
358+ for (String field : dto .getFields ()) {
359+ SqlIdentifierValidator .validate (field );
360+ if (!allowedFields .contains (field )) {
361+ throw new IllegalArgumentException ("不允许的字段: " + field );
362+ }
363+ }
364+ }
365+
366+ if (dto .getOrderBy () != null && !dto .getOrderBy ().isEmpty ()) {
367+ SqlIdentifierValidator .validate (dto .getOrderBy ());
368+ if (!allowedFields .contains (dto .getOrderBy ())) {
369+ throw new IllegalArgumentException ("不允许的排序字段: " + dto .getOrderBy ());
370+ }
371+ }
372+
373+ if (dto .getOrderType () != null ) {
374+ SqlIdentifierValidator .validateOrderType (dto .getOrderType ());
375+ }
376+ }
295377 private Object convertValueByType (Object value , String fieldType , String columnName ) {
296378 try {
297379 switch (fieldType ) {
@@ -525,6 +607,9 @@ public Map<String, Object> createData(DynamicInsert dataDto) {
525607
526608 String tableName = getTableName (dataDto .getNameEn ());
527609 Map <String , Object > record = new HashMap <>(dataDto .getParams ());
610+ for (String col : record .keySet ()) {
611+ SqlIdentifierValidator .validate (col );
612+ }
528613 String userId = loginUserContext .getLoginUserId ();
529614 // 添加系统字段
530615 record .put ("created_by" ,userId );
@@ -606,6 +691,9 @@ public Map<String,Object> updateDateById(DynamicUpdate dto) {
606691 }
607692 Long id = Long .parseLong (params1 .get ("id" ).toString ());
608693 Map <String , Object > updateFields = dto .getData ();
694+ for (String col : updateFields .keySet ()) {
695+ SqlIdentifierValidator .validate (col );
696+ }
609697 String tableName = getTableName (modelId );
610698 StringBuilder sql = new StringBuilder ("UPDATE " + tableName + " SET " );
611699 List <Object > params = new ArrayList <>();
0 commit comments