Request MappingHandlerMappingの経歴を書き直します。
8515 ワード
最近会社の製品は安全審査をしました。バックエンドが提供するインターフェースには安全なHttp方法の不備があります。安全でないHTTP方法は、TRACE、PUT、DELETE、COPYなどを含む。その中で最も一般的なTRACE方法は、主にテストまたは診断のためにサーバによって受信された要求を再現することができ、悪意のある攻撃者は、この方法を利用してクロスストーカー攻撃(すなわちXST攻撃)を行うことができ、これによってフィッシング、管理者のクッキーなどを盗むことができる。
原因分析
この問題を引き起こした原因は実は簡単です。開発者がインターフェースを開発する時に、Request Mappingの中のmethod属性を指定していないからです。Methodが指定されていないとシステムはデフォルトでTRACE以外の7つの方法をサポートします。だから、これは私が書き直したいRequest MappingHandlerMappingの原因です。
もちろん他の方法もあります。例えば、Request Mappingを採用していて、methodを指定していないところを検索して、コードの中でmethodを明確に指定します。この方法は考え方が一番簡単ですが、やはり人は怠け者です。また、将来のコード開発において、もし誰かがMethodを指定しないなら、この問題は当然存在します。だから私たちはhttpインターフェースマッピング関係のロジックをロードするために変更したいです。
Methodが指定されていない場合は、GETとPOSTのみがサポートされます。methodを明確に指定した場合は、指定されたmethodを保留します。
なぜ書き換えたのですか?Request MappingHandlerMappingです。
まず後端から供給されるHttp要求は、Request Mapping(または派生GetMapping/PostMappingなど)によって実現される。http要請を受けた後、http要求を具体的なControllerにマッピングする方法はどうなりますか?答えはHandlerMappingというインターフェイスです。この具体的なマッピングプロセスの詳細は後にしますが、HandlerMappingインターフェースのマッピング方法getHandlerはAbstracthandlerMappingで実現されますが、AbstracthandlerMappingの非抽象的なサブクラスはRequest MapplerMappingです。
Request MappingHandlerMappingのどの方法を書き直しますか?
Request MappingHandlerMappingにおけるget MappingForMethod法から,界面のマッピング情報は,2つの部分から構成されていることがわかる。一部はController類からのRequest Mapping注解であり、一部は方法によるRequest Mapping注解である。したがって、この方法ではcreateRequest MappingInfoを2回呼び出してから再結合します。
ゲートウェイサービスはSpring bootを使って開発されます。
これらの関係:
でも、もう一つのサービスはSpring mvcを採用しています。上の交換は有効ではありません。サービス中のWebApplication Contectは@EnbaleWebMvcで注入する構成ですので。この注釈で導入されたのは実はDelegating WebMvcConfigrationです。
回転:https://heqiao2010.github.io
原因分析
この問題を引き起こした原因は実は簡単です。開発者がインターフェースを開発する時に、Request Mappingの中のmethod属性を指定していないからです。Methodが指定されていないとシステムはデフォルトでTRACE以外の7つの方法をサポートします。だから、これは私が書き直したいRequest MappingHandlerMappingの原因です。
もちろん他の方法もあります。例えば、Request Mappingを採用していて、methodを指定していないところを検索して、コードの中でmethodを明確に指定します。この方法は考え方が一番簡単ですが、やはり人は怠け者です。また、将来のコード開発において、もし誰かがMethodを指定しないなら、この問題は当然存在します。だから私たちはhttpインターフェースマッピング関係のロジックをロードするために変更したいです。
Methodが指定されていない場合は、GETとPOSTのみがサポートされます。methodを明確に指定した場合は、指定されたmethodを保留します。
なぜ書き換えたのですか?Request MappingHandlerMappingです。
まず後端から供給されるHttp要求は、Request Mapping(または派生GetMapping/PostMappingなど)によって実現される。http要請を受けた後、http要求を具体的なControllerにマッピングする方法はどうなりますか?答えはHandlerMappingというインターフェイスです。この具体的なマッピングプロセスの詳細は後にしますが、HandlerMappingインターフェースのマッピング方法getHandlerはAbstracthandlerMappingで実現されますが、AbstracthandlerMappingの非抽象的なサブクラスはRequest MapplerMappingです。
Request MappingHandlerMappingのどの方法を書き直しますか?
Request MappingHandlerMappingにおけるget MappingForMethod法から,界面のマッピング情報は,2つの部分から構成されていることがわかる。一部はController類からのRequest Mapping注解であり、一部は方法によるRequest Mapping注解である。したがって、この方法ではcreateRequest MappingInfoを2回呼び出してから再結合します。
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
}
return info;
}
本当にcreateRequest MappingInfoは代理方法があります。private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition> condition = (element instanceof Class ?
getCustomTypeCondition((Class>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
createRequest MappingInfoで、私たちが変えたいところを見つけました。Request MappingInfoにmethodを設定する時自分のロジックを追加すればいいです。protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, RequestCondition> customCondition) {
return RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name())
.customCondition(customCondition)
.options(this.config)
.build();
}
これで、Request MappingHandlerMappingは以下の通り書き換えられます。public class HttpSafetyRequestMappingHandlerMapping extends RequestMappingHandlerMapping{
private RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
@Override
protected RequestMappingInfo createRequestMappingInfo(RequestMapping requestMapping,
RequestCondition> customCondition) {
// Controller RequestMapping Method, GET POST
RequestMethod[] methods = { RequestMethod.GET, RequestMethod.POST };
if(requestMapping.method().length != 0){
methods = requestMapping.method();
}
return RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(methods)
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name())
.customCondition(customCondition)
.options(config)
.build();
}
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
}
return info;
}
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition> condition = (element instanceof Class ?
getCustomTypeCondition((Class>) element) : getCustomMethodCondition((Method) element));
if(requestMapping == null){
return null;
}
// RequestMapping,Controller
if(element instanceof Class){
return super.createRequestMappingInfo(requestMapping, condition);
} else {
return createRequestMappingInfo(requestMapping, condition);
}
}
@Override
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
super.afterPropertiesSet();
}
}
置き換え方法ゲートウェイサービスはSpring bootを使って開発されます。
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
から入手できます。このような中に一つの内部の種類があります。EnbleWebMvcConfigrationは引き続きcreateRequest MappingHandlerMapping方法を書き直しました。我々は、WebMvcConfigrationSupport類において、Request MappingHandlerMappingの例の取得は、request MappingHandlerMapping法によりBen注釈を追加して実現されることを知っている。これらの関係:
WebMvcConfigurationSupport
^
|
DelegatingWebMvcConfiguration
^
|
EnableWebMvcConfiguration
^ ^
| | @Import
| WebMvcAutoConfigurationAdapter
| ^
| |
| |
WebMvcAutoConfiguration
WebMvcConfigrationSupportのrequest MappingHandlerMapping方法では、Request MappinghanlderMappingは、createRequest Mappler Mappling Handler Mappingを呼び出すことによって実現される。ですから、Request MappinghanlderMappingの実現をカバーするには、createRequest MappingHandlerMappingを書き換えるだけでいいです。EnbleWebMvcConfigrationはこの方法を下記のように書き換えました。 @Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
if (this.mvcRegistrations != null
&& this.mvcRegistrations.getRequestMappingHandlerMapping() != null) {
return this.mvcRegistrations.getRequestMappingHandlerMapping();
}
return super.createRequestMappingHandlerMapping();
}
上記のコードから分かるように、EnbleWebMvcConfigrationはRequest MappingHandlerMappingを差し替える方式を提供しました。それはつまりWebMvcRegistrationです。WebMvcRegistrationはインターフェースであり、デフォルトの空実装があります。WebMvcRegistration sAdapterは、その中をカバーするget Request MappingHandlerMapping方法だけでいいです。@Component
public class SafetyWebMvcRegistrationsAdapter extends WebMvcRegistrationsAdapter{
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new HttpSafetyRequestMappingHandlerMapping();
}
}
これでSping bootでRequest Mappinghandler Mappingを置き換えることができました。でも、もう一つのサービスはSpring mvcを採用しています。上の交換は有効ではありません。サービス中のWebApplication Contectは@EnbaleWebMvcで注入する構成ですので。この注釈で導入されたのは実はDelegating WebMvcConfigrationです。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
@EnbleWebMvcを@Importに置き換えればいいです。またはDelegatingWebMvcConfigrationを書き換えて、createRequest MappingHandlerMapping方法をカバーしてもいいです。回転:https://heqiao2010.github.io