DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Memory Management in Couchbase’s Query Service
  • How to Build Slack App for Audit Requests
  • Idempotency in Distributed Systems: When and Why It Matters
  • Perfecting CRUD Functionality in NextJS

Trending

  • MCP Servers: The Technical Debt That Is Coming
  • System Coexistence: Bridging Legacy and Modern Architecture
  • Optimizing Integration Workflows With Spark Structured Streaming and Cloud Services
  • Unlocking Data with Language: Real-World Applications of Text-to-SQL Interfaces

Basics of CORS (Cross-Origin Resource Sharing)

Want to learn more about using CORS? Check out this post where we look at SOP and CORS and how to implement them on your project.

By 
vikas kasegaonkar user avatar
vikas kasegaonkar
·
Updated Oct. 15, 18 · Presentation
Likes (14)
Comment
Save
Tweet
Share
28.5K Views

Join the DZone community and get the full member experience.

Join For Free

Before learning more about CORS, it's important to familiarize yourself with SOP (Same-Origin Policy).

What Is SOP (Same-Origin Policy)?

SOP is a security mechanism implemented in almost all of the modern browsers. It does not allow documents or scripts loaded from one origin to access resources from other origins. Now, what is the origin? The origin is not only domain. — the origin could be the combination of the Host name, Port number, and URI (Uniform Resource Identifier) Scheme.

Why Is SOP Important?

For any HTTP request to a particular domain, browsers automatically attach any cookies bounded to that domain. Image title

It doesn't matter if a request originates from "your-bank.com" or "malicous.com." As long as the request goes to your-bank.com, the cookies stored for your-bank.com would be used. As you can see, without the Same-Origin Policy, a Cross-Site Request Forgery (CSRF) attack can be relatively simple, assuming that authentication is based solely on a session cookie. That’s one of the reasons the SOP was introduced.

What Is CORS?

For security reasons, SOP is implemented in all latest browsers, and because of that, a website from one origin cannot access resources from a foreign origin, and to make that possible, CORS comes into the picture. In short, CORS is standard of sharing cross-origin resources. This allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.

  • The client and server exchange a set of headers to specify behaviors regarding cross-domain requests.Image title

Examples of Access Control Scenarios

Simple Request

  • The simple request is that the request that doesn't trigger a CORS preflight

  • The only allowed HTTP methods are: GET, HEAD, POST

  • The only allowded values for the 'Content-Type' header are:
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. text/plain

For example, suppose the web content on the domain http://a.com wishes to invoke content on the domain http://b.com. The code of this sort might be used within JavaScript deployed on http//a.com:

      var invocation = new XMLHttpRequest();
      var url = 'http://b.com/resources/public-data/';

      function callOtherDomain() {
            if(invocation) { 
                invocation.open('GET', url, true);
                invocation.onreadystatechange = handler;
                invocation.send(); 
            }
      }  


Let us look at what the browser will send to the server in this case, and let's see how the server responds:

1. The request from "http://a.com" is sent to the other server, "http://b.com," with the following CORS-related headers:

GET /resources/public-data/ HTTP/1.1
Host: b.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://a.com/examples/access-control/simpleXSInvocation.html
Origin: http://a.com


2. The server "http://b.com" responds with the following CORS-related headers.

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61 
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]


In this case, the server responds with an Access-Control-Allow-Origin: * , which means that the resource can be accessed from any domain in a cross-site manner.

  • Preflighted Request: Unlike "simple rquests" (discussed above), "preflighted requests" send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send.

The only allowed HTTP methods are: PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH.

The only allowed values for the 'Content-Type' header other than the below values are:

  • application/x-www-form-urlencoded

  • multipart/form-data

  • text/plain

The following is an example of a request that will be preflighted.

var invocation = new XMLHttpRequest();
var url = 'http://b.com/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Vikas</name></person>';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}


Let's take a look at the full exchange between client and server. The first exchange is the preflight request/response:

1. Preflighted Request:

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://a.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type


2. Response to the preflighted request

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://a.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain


3. Main Request: Once the preflight request is complete, the real request is sent:

POST /resources/post-here/ HTTP/1.1
Host: b.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://a.com/examples/preflightInvocation.html
Content-Length: 55
Origin: http://a.example
Pragma: no-cache
Cache-Control: no-cache


4. Response to the main request:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]


  • Java implementation of CORS Filter:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class CORSFilter
 */
public class CORSSampleFilter implements Filter {

    public CORSFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        System.out.println("CORSFilter HTTP Request: " + request.getMethod());

        // Authorize (allow) all domains to consume the content
        ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Origin", "*");
        ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Methods","GET, OPTIONS, HEAD, PUT, POST");

        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        // For HTTP OPTIONS verb/method reply with ACCEPTED status code -- per CORS handshake
        if (request.getMethod().equals("OPTIONS")) {
            resp.setStatus(HttpServletResponse.SC_ACCEPTED);
            return;
        }

        // pass the request along the filter chain
        chain.doFilter(request, servletResponse);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}


Register this filter in web.xml:

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>com.ksegvikas.examples.cors.CORSSampleFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>


Conclusion

CORS (Cross-Origin Resource Sharing) is the standard way of sharing resources from one origin to another. As SOP (Same-Origin Policy) is for security purpose, which restricts sharing of resources from origin to another, CORS provides us with a standard way to access it with proper implementation, as shown in the above examples.

Requests

Opinions expressed by DZone contributors are their own.

Related

  • Memory Management in Couchbase’s Query Service
  • How to Build Slack App for Audit Requests
  • Idempotency in Distributed Systems: When and Why It Matters
  • Perfecting CRUD Functionality in NextJS

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!