๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๊ฐœ๋ฐœ/Web

[Spring Framework] CORS ์ ์šฉํ•˜๊ธฐ - @CrossOrigin, <mvc:cors>, Filter

by ynzu๐Ÿค 2022. 3. 11.
๋ฐ˜์‘ํ˜•

 

CORS๋ž€?

test2.com:8080์‚ฌ์ดํŠธ์™€ test.com:18080 ์‚ฌ์ดํŠธ๋Š” ๋„๋ฉ”์ธ๊ณผ ํฌํŠธ๊ฐ€ ๋‹ค๋ฅด๋‹ค. ๋”ฐ๋ผ์„œ test.com:18080์—์„œ test2.com:8080์‚ฌ์ดํŠธ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋‹ค.

Access to XMLHttpRequest at 'http://domain1:8080/xxxxx' from origin 'http://test.com:18080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

http://localhost:8080/test/1 ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋น„๊ตํ•ด๋ณด๋ฉด

URL ์ถœ์ฒ˜ ๋น„๊ณ 
http://localhost:8080/test/2  ๋™์ผ์ถœ์ฒ˜ protocol, host, port ๋™์ผ
http://localhost:8080/sample ๋™์ผ์ถœ์ฒ˜ protocol, host, port ๋™์ผ
https://localhost:8080/test ๋‹ค๋ฅธ์ถœ์ฒ˜ protocol ๋‹ค๋ฆ„
http://localhost:18080/test/1 ๋‹ค๋ฅธ์ถœ์ฒ˜ port ๋‹ค๋ฆ„
http://test.com:8080/test/1 ๋‹ค๋ฅธ์ถœ์ฒ˜ host ๋‹ค๋ฆ„

protocol, host, port๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•˜๋ฉด ๋™์ผ์ถœ์ฒ˜์ด๊ณ , ํ•˜๋‚˜๋ผ๋„ ๊ฐ™์ง€ ์•Š์œผ๋ฉด ๋‹ค๋ฅธ์ถœ์ฒ˜์ด๋‹ค.

๋™์ผ์ถœ์ฒ˜๋Š” SOP(Same-Origin Policy)๋กœ ์›น๋ธŒ๋ผ์šฐ์ € ์ƒ์—์„œ ๋ณด์•ˆ์ƒ ์ด์Šˆ๊ฐ€ ์—†์ง€๋งŒ ๋‹ค๋ฅธ์ถœ์ฒ˜์˜ ๊ฒฝ์šฐ ๋ณด์•ˆ์ƒ ์ด์Šˆ๋กœ ์ธํ•ด ์›น๋ธŒ๋ผ์šฐ์ €์ƒ์—์„œ ์—๋Ÿฌ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ , ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” CORS๋ฅผ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

CORS๋Š” Cross-Origin Resource Sharing์˜ ์ค„์ž„๋ง๋กœ ์ง์—ญํ•˜๋ฉด '๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ '๋ผ๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ '๊ต์ฐจ ์ถœ์ฒ˜'๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์€ '๋‹ค๋ฅธ ์ถœ์ฒ˜'๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•˜์ž๋ฉด CORS๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ๊ฒŒํ•˜๋Š” ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.


test.com:18080 ์‚ฌ์ดํŠธ์—์„œ test2.com:8080 ์‚ฌ์ดํŠธ์— ์—‘์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„  ์•„๋ž˜ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

๋ฐฉ๋ฒ• 1 - @CrossOrigin

@CrossOrigin(origins = "http://test.com")

์š”์ฒญ์„ ๋ณด๋‚ด๋Š” client ์‚ฌ์ดํŠธ์˜ ๋„๋ฉ”์ธ์„ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋˜๊ณ ,  Controller๋‚˜ Controller์˜ ๋ฉ”์†Œ๋“œ์— ์ถ”๊ฐ€ํ•˜์—ฌ ํŠน์ • API๋งˆ๋‹ค ์„ค์ • ๊ฐ€๋Šฅํ•˜๋‹ค. 

 

Globalํ•˜๊ฒŒ ์„ค์ •ํ•˜๋ ค๋ฉด ๋ฐฉ๋ฒ•2, ๋ฐฉ๋ฒ•3์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

๋ฐฉ๋ฒ• 2 - <mvc:cors>

servlet-context.xml์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

<mvc:cors>
    <mvc:mapping path="/**" allowed-origins="*" allowed-methods="POST,GET" allow-credentials="true"/>
</mvc:cors>
  • ํŠน์ • ๋„๋ฉ”์ธ๋งŒ ํ—ˆ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด allowed-origins="http://test.com"๋ฅผ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ์—ฌ๋Ÿฌ ํŠน์ • ๋„๋ฉ”์ธ์„ ํ—ˆ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด allowed-origins="http://test.com, http://sample.com"๋ฅผ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. (์ฝค๋งˆ๋กœ ๊ตฌ๋ถ„)

 

๋ฐฉ๋ฒ• 3 - Filter

<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>com.dreamsecurity.framework.filter.CorsFilter</filter-class>
    <init-param>
        <param-name>allow-origin</param-name>
        <param-value>http://sample.com:28080, http://test.com:18080</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>*</url-pattern>
</filter-mapping>

 

public class CorsFilter implements Filter{

	Logger logger = LogManager.getLogger(CorsFilter.class.getName());
	
	private String allowOrigin;
	
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.allowOrigin = (String)filterConfig.getInitParameter("allow-origin");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		
		if(allowOrigin != null) {
			String[] allowOrigins  = allowOrigin.split(",");
			
			boolean isAllowOrigin = false;
			for(String origin : allowOrigins) {
				if(origin.equals(request.getHeader("Origin"))) {
					isAllowOrigin = true;
					break;
				}
			}
			
			if(isAllowOrigin) {
                                response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
                                response.setHeader("Access-Control-Allow-Credentials", "true"); //์ฟ ํ‚ค ์š”์ฒญ์„ ํ—ˆ์šฉ
                                response.setHeader("Access-Control-Allow-Methods","POST, GET"); //ํ—ˆ์šฉํ•  HTTP ๋ฉ”์„œ๋“œ
                                response.setHeader("Access-Control-Allow-Headers", "*"); //์š”์ฒญ์„ ํ—ˆ์šฉํ•  ํ—ค๋”

                                chain.doFilter(req, res);
		        
			}
		}
		
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	} 

}

 

๊ทธ๋ฆฌ๊ณ  ์ธํ„ฐ์…‰ํ„ฐ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

Spring Boot์—์„  ์ฃผ๋กœ WebMvcConfigurer ์—์„œ cors ์„ค์ •์„ ํ•˜๋˜๋ฐ ์ด๋Š” ์ถ”ํ›„ ํฌ์ŠคํŒ…ํ•˜๋Š”๊ฑธ๋กœ..!

 

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€