SPRINGMVC Open Cors Support _SPRINGMVC

Source: Internet
Author: User
Tags id3 uuid
Objective

Browser for security reasons, limited JS to launch a cross-station request, the use of XHR object to initiate a request must follow the homology policy (sop:same Origin Policy), the Cross-site request will be blocked by the browser, which is very painful for developers, especially to develop the front and back separation of the application.

In the modern web development, the resource data sharing is more and more common in different network environment, the homologous strategy can be said to restrict the development of the Web API to some extent.

Simply put, Cors is for Ajax to be secure across domains. As for the safety research of cors, this article does not discuss. Directory

A brief introduction to Cors

How to use. HTTP headers for Cors

Initial Project Preparation

Corsfilter: Cors of the filter stage

Corsinterceptor: Cors of the Interceptor phase

@CrossOrigin: The cors of Handler stage

Summary

The pursuit of the ultimate development experience: integration of Third-party Corsfilter

Sample code Download Cors a brief summary

Terminology interpretation: Cross-domain resource sharing (cross-origin Resource sharing)

Concept: is a cross-domain mechanism, norms, standards, how to call all the same, but this set of standards for the service side, and the browser side as long as the support HTML5 can.

Role: Can let the service side decide which request source can come in to take the data, so the service end plays the leading role (so out of the matter to find Backstage program ape, irrelevant front end ^ ^)

Common scenarios: full separation of the front and back end applications, such as hybrid App open read-only API,JS can access, such as maps, weather, time ... How to use. HTTP headers for Cors

To achieve cors Cross-domain is very simple, in the end, it is a series of HTTP headers in the server, mainly divided into the request headers and response headers, in the request and response to add these HTTP headers can easily achieve cors

The request header and the response header information are set at the server side, usually set in the filter phase, the browser end does not care, the only place to set is: whether to carry the cookie HTTP request header across the domain:

#请求域
Origin: "http://localhost:3000"

#这两个属性只出现在预检请求中, the options request
Access-control-request-method: "POST "
access-control-request-headers:" Content-type "
HTTP Response headers:
#允许向该服务器提交请求的URI, * means all allow, in Springmvc, if set to *, will automatically turn to the Origin Access-control-allow-origin in the current request header
: "http:// localhost:3000 "

#允许访问的头信息
access-control-expose-headers:" Set-cookie "

#预检请求的缓存时间 (seconds), that is, in this time period, The same Cross-domain request is not checked for
access-control-max-age: "1800"

#允许Cookie跨域, useful
when doing login verification Access-control-allow-credentials: "True"

#允许提交请求的方法, * means all allowed
Access-control-allow-methods:get,post,put , Delete,patch
Initial Project Preparation

To add, for simple cross-domain and Get,head Cross-domain, it's understandable that a simple cross-domain is a content-type and a POST request, but that the POST request is only application/x-www-form-urlencoded, Multipart/form-data or Text/plain on the contrary, is not a simple cross-domain, this cross-domain has a pre-inspection mechanism, said straightforward point, that is, will send two requests, an options request, a real request

Start by creating a new static Web project that defines three types of requests: simple Cross-domain requests, not simple cross-domain requests, and requests with cookie information (do login checksums). The code is as follows:

<! DOCTYPE html> Then start the Web project (a WYSIWYG tool is recommended here: Browser-sync)
Browser-sync start--server--files "*.html"

Next, do the service side thing, create a new SPRINGMVC project, here recommend a Web site that automatically generates spring seed projects: http://start.spring.io/

Seed Project

The project structure is as follows:

Project structure

Introduction of Lombok and guava in Pom.xml

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactid>guava</ artifactid>
    <version>19.0</version>
</dependency>

<dependency>
    < groupid>org.projectlombok</groupid>
    <artifactId>lombok</artifactId>
    <version >1.16.8</version>
</dependency>
Analog Data Source: UserDB
public class UserDB {public

    static cache<string, user> UserDB = Cachebuilder.newbuilder (). Expireafterwrite (1 , timeunit.days). Build ();

    static {
        String id1 = Uuid.randomuuid (). toString ();
        String Id2 = Uuid.randomuuid (). toString ();
        String ID3 = Uuid.randomuuid (). toString ();
        Userdb.put (ID1, New User (ID1, "jear"));
        Userdb.put (Id2, New User (Id2, "Tom"));
        Userdb.put (ID3, New User (ID3, "Jack"));
    }
Writing the sample controller: Usercontroller
@RestController
@RequestMapping ("/users") public
class Usercontroller {

    @RequestMapping (method = Requestmethod.get)
    list<user> getlist () {return
        lists.newarraylist (Userdb.asmap (). values ());

    @RequestMapping (method = Requestmethod.post)
    list<string> Add (@RequestBody String name) {
        if ( Userdb.asmap (). values (). Stream (). AnyMatch (User-> user.getname (). Equals (name)) {return
            lists.newarraylist ("Add failed, username '" + name + ' existing ');
        }
        String id = uuid.randomuuid (). toString ();
        Userdb.put (ID, new User (ID, name));
        Return Lists.newarraylist ("Add success:" + userdb.getifpresent (ID));
    }
Writing the sample controller: Userlogincontroller
@RestController
@RequestMapping ("/user/login") public
class Userlogincontroller {

    @RequestMapping ( method = Requestmethod.get)
    Object GetInfo (HttpSession session) {
        object = Session.getattribute (" Loginer ");
        return object = null? Lists.newarraylist ("not Logged in"): Object;
    }

    @RequestMapping (method = requestmethod.post)
    list<string> Login (HttpSession session, @RequestBody String Name) {
        optional<user> User = Userdb.asmap (). values (). Stream (). Filter (User1-> user1.getname (). Equals ( Name)). Findany ();
        if (User.ispresent ()) {
            Session.setattribute ("Loginer", User.get ());
            return lists.newarraylist ("Login succeeded!");
        }
        return lists.newarraylist ("Login failed, user name not found:" + name);
    }
Finally start the service side project
MVN Clean Package
Debug Mode boot Application
Here, the main work is done, open the browser, access the static Web project, open the console, and found that the AJAX request can not get the data, this is the same as the same as the origin of the same strategy. Cors Support Corsfilter: Filter phase Cors
@Configuration public class Webconfig extends Webmvcconfigureradapter {@Bean public filterregistrationbean Filte 
        Rregistrationbean () {//Cors authorization of the response header mycorsregistration corsregistration = new Mycorsregistration ("/**"); Corsregistration.allowedorigins (Crossorigin.default_origins). Allowedmethods (HttpMethod.GET.name ( ), HttpMethod.HEAD.name (), HttpMethod.POST.name (), HttpMethod.PUT.name ()). Allowedheaders (Crossorigin.defa ult_allowed_headers). Exposedheaders (Httpheaders.set_cookie). Allowcredentials (Crossorigin .

        default_allow_credentials). MaxAge (Crossorigin.default_max_age);
        Register cors filter Urlbasedcorsconfigurationsource Configurationsource = new Urlbasedcorsconfigurationsource ();
        Configurationsource.registercorsconfiguration ("/**", Corsregistration.getcorsconfiguration ());
        Corsfilter corsfilter = new Corsfilter (Configurationsource); ReturN New Filterregistrationbean (corsfilter); }
}
Now test "simple cross-domain" and "Not simple Cross-domain", and you can already respond correctly

Browser picture

Let's Test the "login check" and "login" to see if the cookie will work across the domain.

Browser picture

If the service-side allowcredentials is set to false, or if the AJAX request does not take {withcredentials:true}, the login checksum is never logged in, because the cookie is not passed between the browser and the server Corsinterceptor: Cors of the Interceptor phase

Now that you have the filter level of cors, why do you have to corsinterceptor? Because the granularity of control is different. Filter is a front filter for any servlet, and Inteceptor is only valid for blocking requests under Dispatcherservlet, which is the last line of defense required to enter handler, and if a layer of inteceptor defense is set up, can enhance security and controllability.

As for the cors at this stage, I had to spit a few sentences, and spring put Corsinteceptor in the last one on the interceptor chain, which means if I had a custom interceptor, the request would be intercepted by my own interceptor, You can only cross the domain through Corsfilter authorization, and you can't go to Corsinterceptor, as for why, the following will be mentioned.

So Corsinterceptor is written specifically for handler across domains in the authorization.

Nonsense not much to say, directly on the code:

@Configuration public class Webconfig extends Webmvcconfigureradapter {@Bean public filterregistrationbean CORSF Ilterregistrationbean () {//Cors Authorization for response headers mycorsregistration corsregistration = new Mycorsregistration ("/*
        *");

        This._configcorsparams (corsregistration);
        Register cors filter Urlbasedcorsconfigurationsource Configurationsource = new Urlbasedcorsconfigurationsource ();
        Configurationsource.registercorsconfiguration ("/**", Corsregistration.getcorsconfiguration ());
        Corsfilter corsfilter = new Corsfilter (Configurationsource);
    return new Filterregistrationbean (Corsfilter); @Override public void Addcorsmappings (Corsregistry registry) {//configure Corsinterceptor cors parameter this
    . _configcorsparams (Registry.addmapping ("/**")); } private void _configcorsparams (Corsregistration corsregistration) {corsregistration.allowedorigins (CrossOr Igin. Default_origins). AllowedmethoDS (HttpMethod.GET.name (), HttpMethod.HEAD.name (), HttpMethod.POST.name (), HttpMethod.PUT.name ()). Allowedh Eaders (crossorigin.default_allowed_headers). Exposedheaders (Httpheaders.set_cookie). Allow
    Credentials (crossorigin.default_allow_credentials). MaxAge (Crossorigin.default_max_age); }
}
Open the browser, the effect is the same as above @CrossOrigin: Handler stage Cors

If you write the previous code carefully, you should have found this annotation, this annotation is used in the Controller method, in fact, Spring here with the Corsinterceptor, do the last layer of interception, This also explains why Corsinterceptor is always the last interceptor to execute.

This is the minimum control granularity that can be accurate to a request for Cross-domain control

The first two stages of the Webconfig configuration are commented out, and then added to the cross-domain annotation
@CrossOrigin (origins = "http://localhost:3000")
@RequestMapping ( method = Requestmethod.get)
list<user> getlist () {return
    lists.newarraylist (Userdb.asmap (). VALUES ()) ;
}
Opens the browser and finds that only the first request can cross the domain correctly

Handler cross-domain summary

The three-phase cors configuration sequence is superimposed to the front, rather than the back completely covered front, so in the design, each stage how to accurately control the cors, but also in practice to explore slowly ... Pursuing a better development experience: consolidating third party Corsfilter

Use and analysis of this class library will be launched in the next chapter

Official website: http://software.dzhuvinov.com/cors-filter.html

The

prefers to use this corsfilter mainly because it supports cors configuration files, can automatically read cors.properties under Classpath, and the feature sample code for file watching downloads http:// Git.oschina.net/jearton/springmvc-cors http://git.oschina.net/jearton/web-demo/

Text/jearton (author of Jane book)
Original link: http://www.jianshu.com/p/d05303d34222
Copyright belongs to the author, reproduced please contact the author to obtain authorization, and labeled "Jane book author."

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.