接着Spring 5.2.2 MVC (6)--注释控制器讲基于注解控制内容。
java
3)后缀匹配typescript
默认状况下,Spring MVC执行.*后缀模式匹配,以便映射到/person的控制器也隐蔽映射到/person.*。而后使用文件扩展名解释请求的内容类型以用于响应(即,代替Accept
头) - ,例如/person.pdf
, /person.xml
和其余。编程
当浏览器用来发送难以一致的Accept
头时,以这种方式使用文件扩展名是必要的。目前,这已再也不是必需的,使用Accept
头应该是首选。json
随着时间的推移,文件扩展名的使用已经被证实在许多方面存在问题。当使用URI变量、路径参数和URI编码覆盖时,它可能会致使歧义。关于基于URL的受权和安全性的推理也变得更加困难。浏览器
要彻底禁用文件扩展名的使用,必须同时设置如下两项:安全
useSuffixPatternMatching(false)
--参看PathMatchConfigurer
微信favorPathExtension(false)
--参看ContentNegotiationConfigure
app
基于URL的内容仍然颇有用(例如,在浏览器中键入URL时)。为了实现这一点,咱们建议使用基于查询参数的策略,以免文件扩展名带来的大多数问题。或者,若是必须使用文件扩展名,请考虑经过ContentNegotiationConfigurer
的mediaTypes
属性将它们限制为显式注册的扩展名列表。ide
public class WebConfig implements WebMvcConfigurer {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.mediaType("json", MediaType.APPLICATION_JSON); configurer.mediaType("xml", MediaType.APPLICATION_XML); }}
4)后缀匹配和RFD测试
反射文件下载(reflected file download,RFD)攻击与XSS相似,它依赖于响应中反射的请求输入(例如,查询参数和URI变量)。然而RFD攻击不是将JavaScript插入HTML,而是依赖于浏览器切换来执行下载,并在之后双击时将响应视为可执行脚本。
在Spring MVC中,@ResponseBody和ResponseEntity
方法面临风险,由于它们能够呈现不一样的内容类型,客户端能够经过URL路径扩展请求这些内容类型。禁用后缀模式匹配和使用路径扩展进行内容能够下降风险,但不足以防止RFD攻击。
为了防止RFD攻击,在呈现响应体以前,Spring MVC添加了一个:Content-Disposition:inline;filename=f.txt头来建议一个固定且安全的下载文件。只有当URL路径包含既没有白名单也没有为内容显式注册的文件扩展名时,才会执行此操做。然而,当URL直接输入到浏览器中时,它可能会产生反作用。
默认状况下,许多公共路径扩展都是白名单。具备自定义HttpMessageConverter
实现的应用程序能够注册用于内容的文件扩展名,以免为这些扩展名添加Content-Disposition头。
有关RFD的其余建议,见CVE-2015-5211。
5)Consumable 媒体Types
能够根据请求的Content-Type缩小请求映射范围,以下例所示:
//使用consumes属性缩小Content-Type映射范围。"/pets", consumes = "application/json") (path = public void addPet( Pet pet) { // ...}
consumes
属性还支持否认表达式 - ,例如!text/plain是指除text/plain之外的任何内容类型。
能够在类级别声明一个共享consumes
属性。然而,与大多数其余请求映射属性不一样,当在类级别使用时,方法级别使用consumes
属性重写,而不是扩展类级别声明。
MediaType
为经常使用的媒体类型(如APPLICATION_JSON_VALUE
和APPLICATION_XML_VALUE)提供常量。
6)Producible 媒体 Types
能够基于Accept
请求头和控制器方法生成的内容类型列表缩小请求映射,以下例所示:
//使用products属性缩小content type映射范围。"/pets/{petId}", produces = "application/json") (path = public Pet getPet( String petId) { // ...}
媒体类型能够指定字符集。例如,支持否认表达式 -!text/plain是指除“text/plain”以外的任何内容类型。
能够在类级别声明共享的produces
属性。可是,与大多数其余请求映射属性不一样,当在类级别使用时,方法级别生成produces
属性重写,而不是扩展类级别声明。
7)Parameters, headers
能够基于请求参数条件缩小请求映射范围。你能够测试是否存在请求参数(myParam),是否缺乏一个(!myPara)或特定值(myParam=myValue)。如下示例演示如何测试特定值:
//测试myParam是否等于myValue"/pets/{petId}", params = "myParam=myValue") (path = public void findPet( String petId) { // ...}
你还能够对请求头条件使用相同的条件,以下例所示:
//测试myHeader是否等于myvalue。"/pets", headers = "myHeader=myValue") (path = public void findPet( String petId) { // ...}
你能够将Content-Type和Accept
与headers条件匹配,但最好使用consumers
和products
。
8)HTTP HEAD, OPTIONS
@GetMapping(和@RequestMapping(method=HttpMethod.GET))为请求映射支持HTTP HEAD 。控制器方法不须要更改。在javax.servlet.http.HttpServlet中应用的response 封装确保将Content-Length头设置为写入的字节数(而不实际写入响应)。
@GetMapping(和@RequestMapping(method=HttpMethod.GET))隐式映射到并支持HTTP HEAD。一个HTTP HEAD请求被看成HTTP GET来处理,只是不写正文,而是计算字节数并设置Content-Length头。
默认状况下,经过将Allow
response头设置为全部@RequestMapping方法中列出的具备匹配URL模式的HTTP方法列表来处理HTTP选项。
对于没有HTTP方法声明的@RequestMapping,Allow
头被设置为GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS。控制器方法应始终声明支持的HTTP方法(例如,使用HTTP方法特定的变量:@GetMapping、@PostMapping和其余变量)。
你能够将@RequestMapping方法映射到HTTP HEAD和HTTP OPTIONS,但在通常状况下这是不必的。
9)自定义注解
Spring MVC支持使用组合注解进行请求映射。这些注解自己就是用@RequestMapping进行元注解的注解,用于从新声明@RequestMapping属性的一个子集(或所有),具备更窄、更具体的用途。
@GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
, 和@PatchMapping是组合注解的示例。之因此提供它们,是由于大多数控制器方法应该映射到特定的HTTP方法,而不是使用@RequestMapping,默认状况下,它与全部HTTP方法匹配。若是须要组合注解的示例,请查看如何声明这些注释。
Spring MVC还支持具备自定义请求匹配逻辑的自定义请求映射属性。这是一个更高级的选项,须要子类RequestMappingHandlerMapping
并重写getCustomMethodCondition
方法,你能够在该方法中检查自定义属性并返回本身的RequestCondition。
10)易于理解的Registrations
你能够以编程方式注册处理程序方法,这些方法可用于动态注册或高级状况,例如不一样URL下同一处理程序的不一样实例。如下示例注册处理程序方法:
public class MyConfig { //为控制器注入目标处理程序和处理程序映射。 public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) throws NoSuchMethodException { //准备请求映射数据。 RequestMappingInfo info = RequestMappingInfo .paths("/user/{id}").methods(RequestMethod.GET).build(); //获取处理程序方法 Method method = UserHandler.class.getMethod("getUser", Long.class); //添加注册。 mapping.registerMapping(info, handler, method); }}
明天讲 基于控制器注解的句柄方法(Handler Methods)。
敬请持续关注。
欢迎关注和转发Spring中文社区(加微信群,能够关注后加我微信):
本文分享自微信公众号 - Spring中文社区(gh_81d233bb13a4)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。