mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Modify sinks
This commit is contained in:
@@ -16,15 +16,14 @@ import DataFlow::PathGraph
|
||||
import MyBatisMapperXmlSqlInjectionLib
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for tracking untrusted user input used by the Mybatis mapper xml file dynamic splicing sql use.
|
||||
*/
|
||||
private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::Configuration {
|
||||
MyBatisMapperXmlSqlInjectionConfiguration() { this = "MyBatis mapper xml sql injection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof MyBatisMapperXmlSqlInjectionSink }
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof MyBatisMapperXmlSqlInjectionSink
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.getType() instanceof PrimitiveType or
|
||||
@@ -33,7 +32,8 @@ private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::C
|
||||
}
|
||||
}
|
||||
|
||||
from MyBatisMapperXmlSqlInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
from
|
||||
MyBatisMapperXmlSqlInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "MyBatis Mapper XML sql injection might include code from $@.", source.getNode(),
|
||||
"this user input"
|
||||
select sink.getNode(), source, sink, "MyBatis Mapper XML sql injection might include code from $@.",
|
||||
source.getNode(), "this user input"
|
||||
|
||||
@@ -2,24 +2,100 @@ import java
|
||||
import semmle.code.xml.MyBatisMapperXML
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/** The interface `org.apache.ibatis.annotations.Param`. */
|
||||
private class TypeParam extends Interface {
|
||||
TypeParam() { this.hasQualifiedName("org.apache.ibatis.annotations", "Param") }
|
||||
}
|
||||
|
||||
/** A sink for MyBatis Mapper XML file sql injection vulnerabilities. */
|
||||
class MyBatisMapperXmlSqlInjectionSink extends DataFlow::Node {
|
||||
MyBatisMapperXmlSqlInjectionSink() {
|
||||
exists(MyBatisMapperSqlOperation mbmxe, MethodAccess ma |
|
||||
mbmxe.getAChild*().getTextValue().trim().matches("%${%") and
|
||||
mbmxe.getId() = ma.getMethod().getName() and
|
||||
ma.getMethod().getDeclaringType() =
|
||||
mbmxe.getParent().(MyBatisMapperXMLElement).getNamespaceRefType() and
|
||||
ma.getAnArgument() = this.asExpr()
|
||||
)
|
||||
abstract class MyBatisMapperXmlSqlInjectionSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sink for MyBatis Mapper method parameter name sql injection vulnerabilities.
|
||||
*
|
||||
* e.g. MyBatis Mapper method: `void test(String name);` and MyBatis Mapper XML file:`select id,name from test where name like '%${name}%'`
|
||||
*/
|
||||
class MyBatisMapperParameterNameSqlInjectionSink extends MyBatisMapperXmlSqlInjectionSink {
|
||||
MyBatisMapperParameterNameSqlInjectionSink() {
|
||||
exists(
|
||||
MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess ma, int i, Method m,
|
||||
Expr arg, string sql
|
||||
|
|
||||
m = ma.getMethod() and arg = ma.getArgument(i)
|
||||
|
|
||||
arg = this.asExpr() and
|
||||
(
|
||||
mbmxe.getAChild*().getTextValue().trim() = sql
|
||||
or
|
||||
exists(MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess ma |
|
||||
mbmxe.getInclude().getRefid() = mbms.getId() and
|
||||
mbms.getAChild*().getTextValue().trim().matches("%${%") and
|
||||
mbms.getAChild*().getTextValue().trim() = sql
|
||||
) and
|
||||
not m.getParameter(i).hasAnnotation() and
|
||||
sql.matches("%${" + m.getParameter(i).getName() + "%") and
|
||||
mbmxe.getId() = ma.getMethod().getName() and
|
||||
ma.getMethod().getDeclaringType() =
|
||||
mbmxe.getParent().(MyBatisMapperXMLElement).getNamespaceRefType() and
|
||||
ma.getAnArgument() = this.asExpr()
|
||||
mbmxe.getParent().(MyBatisMapperXMLElement).getNamespaceRefType()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for MyBatis Mapper method Param Annotation sql injection vulnerabilities.
|
||||
*
|
||||
* e.g. MyBatis Mapper method: `void test(@Param("orderby") String name);` and MyBatis Mapper XML file:`select id,name from test order by ${orderby,jdbcType=VARCHAR}`
|
||||
*/
|
||||
class MyBatisMapperParamAnnotationSqlInjectionSink extends MyBatisMapperXmlSqlInjectionSink {
|
||||
MyBatisMapperParamAnnotationSqlInjectionSink() {
|
||||
exists(
|
||||
MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess ma, int i, Method m,
|
||||
Expr arg, Annotation a, string sql
|
||||
|
|
||||
m = ma.getMethod() and arg = ma.getArgument(i)
|
||||
|
|
||||
arg = this.asExpr() and
|
||||
(
|
||||
mbmxe.getAChild*().getTextValue().trim() = sql
|
||||
or
|
||||
mbmxe.getInclude().getRefid() = mbms.getId() and
|
||||
mbms.getAChild*().getTextValue().trim() = sql
|
||||
) and
|
||||
m.getParameter(i).hasAnnotation() and
|
||||
m.getParameter(i).getAnAnnotation() = a and
|
||||
a.getType() instanceof TypeParam and
|
||||
sql.matches("%${" + a.getValue("value").(CompileTimeConstantExpr).getStringValue() + "%") and
|
||||
mbmxe.getId() = ma.getMethod().getName() and
|
||||
ma.getMethod().getDeclaringType() =
|
||||
mbmxe.getParent().(MyBatisMapperXMLElement).getNamespaceRefType()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for MyBatis Mapper method Class Field sql injection vulnerabilities.
|
||||
*
|
||||
* e.g. MyBatis Mapper method: `void test(Test test);` and MyBatis Mapper XML file:`select id,name from test order by ${name,jdbcType=VARCHAR}`
|
||||
*/
|
||||
class MyBatisMapperClassFieldSqlInjectionSink extends MyBatisMapperXmlSqlInjectionSink {
|
||||
MyBatisMapperClassFieldSqlInjectionSink() {
|
||||
exists(
|
||||
MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess ma, int i, Method m,
|
||||
Expr arg, string sql, Class c
|
||||
|
|
||||
m = ma.getMethod() and arg = ma.getArgument(i)
|
||||
|
|
||||
arg = this.asExpr() and
|
||||
(
|
||||
mbmxe.getAChild*().getTextValue().trim() = sql
|
||||
or
|
||||
mbmxe.getInclude().getRefid() = mbms.getId() and
|
||||
mbms.getAChild*().getTextValue().trim() = sql
|
||||
) and
|
||||
not m.getParameter(i).hasAnnotation() and
|
||||
m.getParameterType(i).getName() = c.getName() and
|
||||
sql.matches("%${" + c.getAField().getName() + "%") and
|
||||
mbmxe.getId() = ma.getMethod().getName() and
|
||||
ma.getMethod().getDeclaringType() =
|
||||
mbmxe.getParent().(MyBatisMapperXMLElement).getNamespaceRefType()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
edges
|
||||
| MybatisSqlInjection.java:16:25:16:35 | name : String | MybatisSqlInjection.java:17:55:17:58 | name : String |
|
||||
| MybatisSqlInjection.java:17:55:17:58 | name : String | MybatisSqlInjectionService.java:11:25:11:35 | name : String |
|
||||
| MybatisSqlInjection.java:22:25:22:35 | name : String | MybatisSqlInjection.java:23:55:23:58 | name : String |
|
||||
| MybatisSqlInjection.java:23:55:23:58 | name : String | MybatisSqlInjectionService.java:16:25:16:35 | name : String |
|
||||
| MybatisSqlInjection.java:28:25:28:35 | name : String | MybatisSqlInjection.java:29:55:29:58 | name : String |
|
||||
| MybatisSqlInjection.java:29:55:29:58 | name : String | MybatisSqlInjectionService.java:21:25:21:35 | name : String |
|
||||
| MybatisSqlInjection.java:34:19:34:40 | test : Test | MybatisSqlInjection.java:35:35:35:38 | test : Test |
|
||||
| MybatisSqlInjection.java:35:35:35:38 | test : Test | MybatisSqlInjectionService.java:26:19:26:27 | test : Test |
|
||||
| MybatisSqlInjection.java:39:19:39:40 | test : Test | MybatisSqlInjection.java:40:35:40:38 | test : Test |
|
||||
| MybatisSqlInjection.java:40:35:40:38 | test : Test | MybatisSqlInjectionService.java:30:19:30:27 | test : Test |
|
||||
| MybatisSqlInjection.java:17:25:17:35 | name : String | MybatisSqlInjection.java:18:55:18:58 | name : String |
|
||||
| MybatisSqlInjection.java:18:55:18:58 | name : String | MybatisSqlInjectionService.java:11:25:11:35 | name : String |
|
||||
| MybatisSqlInjection.java:23:25:23:35 | name : String | MybatisSqlInjection.java:24:55:24:58 | name : String |
|
||||
| MybatisSqlInjection.java:24:55:24:58 | name : String | MybatisSqlInjectionService.java:16:25:16:35 | name : String |
|
||||
| MybatisSqlInjection.java:29:25:29:49 | test : Test | MybatisSqlInjection.java:30:55:30:58 | test : Test |
|
||||
| MybatisSqlInjection.java:30:55:30:58 | test : Test | MybatisSqlInjectionService.java:21:25:21:33 | test : Test |
|
||||
| MybatisSqlInjection.java:35:19:35:40 | test : Test | MybatisSqlInjection.java:36:35:36:38 | test : Test |
|
||||
| MybatisSqlInjection.java:36:35:36:38 | test : Test | MybatisSqlInjectionService.java:26:19:26:27 | test : Test |
|
||||
| MybatisSqlInjection.java:40:19:40:40 | test : Test | MybatisSqlInjection.java:41:35:41:38 | test : Test |
|
||||
| MybatisSqlInjection.java:41:35:41:38 | test : Test | MybatisSqlInjectionService.java:30:19:30:27 | test : Test |
|
||||
| MybatisSqlInjectionService.java:11:25:11:35 | name : String | MybatisSqlInjectionService.java:12:47:12:50 | name |
|
||||
| MybatisSqlInjectionService.java:16:25:16:35 | name : String | MybatisSqlInjectionService.java:17:47:17:50 | name |
|
||||
| MybatisSqlInjectionService.java:21:25:21:35 | name : String | MybatisSqlInjectionService.java:22:47:22:50 | name |
|
||||
| MybatisSqlInjectionService.java:21:25:21:33 | test : Test | MybatisSqlInjectionService.java:22:47:22:50 | test |
|
||||
| MybatisSqlInjectionService.java:26:19:26:27 | test : Test | MybatisSqlInjectionService.java:27:27:27:30 | test |
|
||||
| MybatisSqlInjectionService.java:30:19:30:27 | test : Test | MybatisSqlInjectionService.java:31:27:31:30 | test |
|
||||
nodes
|
||||
| MybatisSqlInjection.java:16:25:16:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:17:55:17:58 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:22:25:22:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:23:55:23:58 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:28:25:28:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:29:55:29:58 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:34:19:34:40 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:35:35:35:38 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:39:19:39:40 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:40:35:40:38 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:17:25:17:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:18:55:18:58 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:23:25:23:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:24:55:24:58 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjection.java:29:25:29:49 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:30:55:30:58 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:35:19:35:40 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:36:35:36:38 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:40:19:40:40 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjection.java:41:35:41:38 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjectionService.java:11:25:11:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjectionService.java:12:47:12:50 | name | semmle.label | name |
|
||||
| MybatisSqlInjectionService.java:16:25:16:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjectionService.java:17:47:17:50 | name | semmle.label | name |
|
||||
| MybatisSqlInjectionService.java:21:25:21:35 | name : String | semmle.label | name : String |
|
||||
| MybatisSqlInjectionService.java:22:47:22:50 | name | semmle.label | name |
|
||||
| MybatisSqlInjectionService.java:21:25:21:33 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjectionService.java:22:47:22:50 | test | semmle.label | test |
|
||||
| MybatisSqlInjectionService.java:26:19:26:27 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjectionService.java:27:27:27:30 | test | semmle.label | test |
|
||||
| MybatisSqlInjectionService.java:30:19:30:27 | test : Test | semmle.label | test : Test |
|
||||
| MybatisSqlInjectionService.java:31:27:31:30 | test | semmle.label | test |
|
||||
#select
|
||||
| MybatisSqlInjectionService.java:12:47:12:50 | name | MybatisSqlInjection.java:16:25:16:35 | name : String | MybatisSqlInjectionService.java:12:47:12:50 | name | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:16:25:16:35 | name | this user input |
|
||||
| MybatisSqlInjectionService.java:17:47:17:50 | name | MybatisSqlInjection.java:22:25:22:35 | name : String | MybatisSqlInjectionService.java:17:47:17:50 | name | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:22:25:22:35 | name | this user input |
|
||||
| MybatisSqlInjectionService.java:22:47:22:50 | name | MybatisSqlInjection.java:28:25:28:35 | name : String | MybatisSqlInjectionService.java:22:47:22:50 | name | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:28:25:28:35 | name | this user input |
|
||||
| MybatisSqlInjectionService.java:27:27:27:30 | test | MybatisSqlInjection.java:34:19:34:40 | test : Test | MybatisSqlInjectionService.java:27:27:27:30 | test | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:34:19:34:40 | test | this user input |
|
||||
| MybatisSqlInjectionService.java:31:27:31:30 | test | MybatisSqlInjection.java:39:19:39:40 | test : Test | MybatisSqlInjectionService.java:31:27:31:30 | test | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:39:19:39:40 | test | this user input |
|
||||
| MybatisSqlInjectionService.java:12:47:12:50 | name | MybatisSqlInjection.java:17:25:17:35 | name : String | MybatisSqlInjectionService.java:12:47:12:50 | name | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:17:25:17:35 | name | this user input |
|
||||
| MybatisSqlInjectionService.java:17:47:17:50 | name | MybatisSqlInjection.java:23:25:23:35 | name : String | MybatisSqlInjectionService.java:17:47:17:50 | name | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:23:25:23:35 | name | this user input |
|
||||
| MybatisSqlInjectionService.java:22:47:22:50 | test | MybatisSqlInjection.java:29:25:29:49 | test : Test | MybatisSqlInjectionService.java:22:47:22:50 | test | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:29:25:29:49 | test | this user input |
|
||||
| MybatisSqlInjectionService.java:27:27:27:30 | test | MybatisSqlInjection.java:35:19:35:40 | test : Test | MybatisSqlInjectionService.java:27:27:27:30 | test | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:35:19:35:40 | test | this user input |
|
||||
| MybatisSqlInjectionService.java:31:27:31:30 | test | MybatisSqlInjection.java:40:19:40:40 | test : Test | MybatisSqlInjectionService.java:31:27:31:30 | test | MyBatis Mapper XML sql injection might include code from $@. | MybatisSqlInjection.java:40:19:40:40 | test | this user input |
|
||||
|
||||
@@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@@ -25,8 +26,8 @@ public class MybatisSqlInjection {
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public List<Test> bad3(String name) {
|
||||
List<Test> result = mybatisSqlInjectionService.bad3(name);
|
||||
public List<Test> bad3(@ModelAttribute Test test) {
|
||||
List<Test> result = mybatisSqlInjectionService.bad3(test);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ public class MybatisSqlInjectionService {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Test> bad3(String name) {
|
||||
List<Test> result = sqlInjectionMapper.bad3(name);
|
||||
public List<Test> bad3(Test test) {
|
||||
List<Test> result = sqlInjectionMapper.bad3(test);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Mapper
|
||||
@@ -8,11 +9,11 @@ public interface SqlInjectionMapper {
|
||||
|
||||
List<Test> bad1(String name);
|
||||
|
||||
List<Test> bad2(String name);
|
||||
List<Test> bad2(@Param("orderby") String name);
|
||||
|
||||
List<Test> bad3(String name);
|
||||
List<Test> bad3(Test test);
|
||||
|
||||
void bad4(Test test);
|
||||
void bad4(@Param("test") Test test);
|
||||
|
||||
void bad5(Test test);
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<if test="name != null">
|
||||
and name = ${name}
|
||||
<if test="test.name != null">
|
||||
and name = ${test.name,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="id != null">
|
||||
and id = #{id}
|
||||
<if test="test.id != null">
|
||||
and id = #{test.id}
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
@@ -24,19 +24,19 @@
|
||||
select id,name from test where name like '%${name}%'
|
||||
</select>
|
||||
|
||||
<select id="bad2" parameterType="java.lang.String" resultMap="BaseResultMap">
|
||||
select id,name from test order by ${name} desc
|
||||
<select id="bad2" resultMap="BaseResultMap">
|
||||
select id,name from test order by ${orderby,jdbcType=VARCHAR} desc
|
||||
</select>
|
||||
|
||||
<select id="bad3" parameterType="java.lang.String" resultMap="BaseResultMap">
|
||||
select id,name from test where name in ${name}
|
||||
</select>
|
||||
|
||||
<update id="bad4" parameterType="Test">
|
||||
<update id="bad4" parameterType="com.example.demo.entity.Test">
|
||||
update test
|
||||
<set>
|
||||
<if test="pass != null">
|
||||
pass = #{pass},
|
||||
<if test="test.pass != null">
|
||||
pass = #{test.pass},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
|
||||
14
java/ql/test/stubs/org.mybatis-3.5.4/org/apache/ibatis/annotations/Param.java
generated
Normal file
14
java/ql/test/stubs/org.mybatis-3.5.4/org/apache/ibatis/annotations/Param.java
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
package org.apache.ibatis.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER})
|
||||
public @interface Param {
|
||||
String value();
|
||||
}
|
||||
21
java/ql/test/stubs/springframework-5.3.8/org/springframework/web/bind/annotation/ModelAttribute.java
generated
Normal file
21
java/ql/test/stubs/springframework-5.3.8/org/springframework/web/bind/annotation/ModelAttribute.java
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target({ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ModelAttribute {
|
||||
@AliasFor("name")
|
||||
String value() default "";
|
||||
|
||||
@AliasFor("value")
|
||||
String name() default "";
|
||||
|
||||
boolean binding() default true;
|
||||
}
|
||||
Reference in New Issue
Block a user