๐ ํด๋น ์ค์ต์ ํ๊ธฐ ์ ์๋์ ๊ฒ์๋ฌผ์ ์ฐธ๊ณ ํ์ฌ ์คํ๋ง ์ํ๋ฆฌํฐ ์ค์ ์ ์๋ฃํด์ผํฉ๋๋ค.
2021.08.19 - [Spring/๊ฐ๋ ์ง์ ๋ฐ ์๋ฌ์ฌํญ] - [Spring] Spring Web Security ์ค์ ํ๊ธฐ
์ํ๋ฆฌํฐ๊ฐ ํ์ํ URL ์ค๊ณ
์ํ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ดํด์ผํ๋ URL์ ์ค๊ณํ๋ ์์ ์ ์ค์ตํด๋ณด์.
1. ๋ก๊ทธ์ธ์ ํ์ง ์์ ์ฌ์ฉ์๋ ์ ๊ทผ ๊ฐ๋ฅํ URL โ /sample/all
2. ๋ก๊ทธ์ธ ํ ์ฌ์ฉ์๋ค์ด ์ ๊ทผํ ์ ์๋ URL โ /sample/member
3. ๋ก๊ทธ์ธ ํ ์ฌ์ฉ์๋ค ์ค์์๋ ๊ด๋ฆฌ์ ๊ถํ์ ๊ฐ์ง ์ฌ์ฉ์๋ง์ด ์ ๊ทผํ ์ ์๋ URL โ /sample/admin
์์ ์ธ๊ฐ์ง ๊ท์น์ ๋ง๊ฒ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ ์ฝ๋๊ฐ ๋์ฌ ๊ฒ์ด๋ค.
SampleController.java
package com.taeong.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
@RequestMapping("/sample/*")
@AllArgsConstructor
public class SampleController {
@GetMapping("/all")
public void doAll() {
log.info("do all can access everybody.");
}
@GetMapping("/member")
public void doMember() {
log.info("logined member");
}
@GetMapping("/admin")
public void doAdmin() {
log.info("admin only");
}
}
url์ ๋ง๋ ๊ฐ๊ฐ์ ํ๋ฉด์ ์์ฑํ๋ค. (jspํ์ผ์ด ์ธ ๊ฐ ๋์ค๋ฉด ๋จ)
url์ ํด๋นํ๋ ํ์ด์ง๋ณ๋ก ์ ๊ทผํ๋ ์ฌ์ฉ์์ ๊ถํ์ ๋ถ์ฌํ๊ธฐ ์ํด์๋ ๋ค์ ๋ด์ฉ์ ํ์ตํด์ผ ํ๋ค.
(์คํ๋ง ์ํ๋ฆฌํฐ์์ ๊ฐ์ฅ ์ค์ํ ์ฉ์ด๋ค์ด๋ผ๊ณ ํ๋ค.)
Authentication(์ธ์ฆ) : ์์ ์ ์ฆ๋ช ํ๋ ๊ฒ
Authorization(๊ถํ) : ๋จ์๊ฒ ์๊ฒฉ์ ๋ถ์ฌ๋ฐ๋ ๊ฒ
๊ทธ๋๊น... 'Authentication'์ ๋ก๊ทธ์ธ๊ฐ์ด ๋ด๊ฐ ์ ๊ทผํ๊ธฐ ์ํด ์ฆ๋ช ํ๋ ์์ ์ด๊ณ ,
'Authorization'๋ ๋ด๊ฐ ๋ง์ฝ ๊ด๋ฆฌ์์ธ ๊ฒฝ์ฐ, ๊ด๋ฆฌ์๊ฐ ์ ๊ทผํ ์ ์๋ ๊ถํ์ ๋ถ์ฌ๋ฐ๋ ๊ฒ!
์คํ๋ง ์ํ๋ฆฌํฐ์๋ ์ธ์ฆ ๋ด๋น์ ์ญํ ์ ํ๋ AuthenticationManager(์ธ์ฆ ๋งค๋์ )๊ฐ ์๋ค.
์ฌ๋ฌ provider๋ฅผ ์ฒ๋ฆฌํ๋ ProviderManager๋ ์ธ์ฆ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ AuthenticationProvider(์ธ์ฆ ์ ๊ณต์)๋ผ๋ ํ์ ์ ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ค.
AuthenticationProvider๋ ์ค์ ์ธ์ฆ ์์ ์ ์งํํ๋ค.
์ด๋, ์ธ์ฆ๋ ์ ๋ณด์๋ ๊ถํ์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ด ์ ๋ฌํ๊ฒ ๋๋๋ฐ(์ผ๋ฐ ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ์ ๊ด๋ฆฌ์์ธ ๊ฒฝ์ฐ์ ๊ถํ์ด ๊ฐ๊ฐ ๋ค๋ฅธ ๊ฒ ์ฒ๋ผ ์ธ์ฆ ์ ๋ณด๋ง๋ค ๊ถํ์ด ๋ค๋ฅผ ์ ์์) ์ด ์ฒ๋ฆฌ๋ UserDetailsService๊ฐ ์ํํ๋ค.
UserDetailsService๋ ์ฌ์ฉ์์ ์ ๋ณด์ ์ฌ์ฉ์๊ฐ ๊ฐ์ง ๊ถํ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํด์ ๋ฐํํด์ค๋ค.
๊ฐ๋ฐ์๊ฐ ์คํ๋ง ์ํ๋ฆฌํฐ๋ฅผ ์ปค์คํฐ๋ง์ด์งํ๋ ๋ฐฉ์
1. UserDetailsService๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์ - ์ค์ ์ฒ๋ฆฌ๋ฅผ ๋ด๋น
2. AuthenticationProvider๋ฅผ ์ง์ ๊ตฌํํ๋ ๋ฐฉ์
-> ์๋ก์ด ํ๋กํ ์ฝ์ด๋ ์ธ์ฆ ๊ตฌํ ๋ฐฉ์์ ์ง์ ๊ตฌํํ๋ ๊ฒฝ์ฐ์ ์ ํฉ
ํด๋น ๊ฒ์๋ฌผ์์ ์ค์ตํด๋ณผ ๊ฒ์ ๋ญ๊ฐ ๊ทธ๋ค์ง ๋ฉ์์ง๋ ์์ง๋ง๐คทโ๏ธ
์ฝ๊ฐ์ ์ค์ ๋ง์ผ๋ก ๋ก๊ทธ์ธ๊ณผ ์ ๊ทผ์ ํ์ ํ ์ ์๋ ๊ธฐ๋ฅ์ด๋ค.
security-context.xml์ ์๋์ ๊ฐ์ด ์ ๊ทผ ์ ํ์ ์ค์ ํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http>
<security:intercept-url pattern="/sample/all" access="permitAll"/>
<security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')"/>
<security:form-login />
</security:http>
<security:authentication-manager>
</security:authentication-manager>
</beans>
<security:intercept-url> : ํน์ ํ URL์ ์ ๊ทผํ ๋ ์ธํฐ์ ํฐ๋ฅผ ์ด์ฉํด์ ์ ๊ทผ์ ์ ํํ๋ ์ค์ ์ ํ๋ ๊ฒฝ์ฐ ์ด์ฉ
pattern : url์ ํจํด
access : ๊ถํ ์ฒดํฌ
๋ ์์ฑ์ ๋ฐ๋์ <security:intercept-url>์์ ์ง์ ํด์ฃผ์ด์ผ ํ๋ ํ์ ์์ฑ์ด๋ผ๋ ๊ฒ์ ๊ธฐ์ตํด๋์!
์์ ์ฝ๋์ ์ผ๋ถ๋ถ์ ์ค๋ช ํ์๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ด๋ค.
<security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')"/>
== '/sample/member'๋ผ๋ url์ ROLE_MEMBER๋ผ๋ ๊ถํ์ด ์๋ ์ฌ์ฉ์๋ง ์ ๊ทผํ ์ ์๋ค.
access์ ์์ฑ๊ฐ์ผ๋ก ์ฌ์ฉ๋๋ ๋ฌธ์์ด๋ก ๋ค์ ๋ ๊ฐ์ง๋ฅผ ์ด์ฉํ ์ ์๋ค.
1) ํํ์ โ ์ค์ต์์๋ ํํ์์ ์ด์ฉํ๋ค.
2) ๊ถํ๋ช (๋จ์ ๋ฌธ์์ด)
๐ ์ค์ต์์๋ ๋ค๋ฃจ์ง ์์ง๋ง access์ ์์ฑ๊ฐ์ผ๋ก ๋จ์ ๋ฌธ์์ด์ ์ด์ฉํ๋ ๊ฒฝ์ฐ
์๋์ ๊ฐ์ด use-expressions๋ฅผ false๋ก ์ง์ ํด์ ํํ์์ ์ฌ์ฉํ์ง ์๋๋ค๋ ๊ฒ์ ์๋ ค์ค๋ค.
(<security:http>๋ ๊ธฐ๋ณธ ์ค์ ์ด ํํ์์ ์ด์ฉํ๋ ๊ฒ)
<security:http auto-config="true" use-expressions="false">
<security:intercept-url pattern="/sample/userPage" access="ROLE_MEMBER" />
<security:intercept-url pattern="/sample/adminPage" access="ROLE_ADMIN" />
๊ทธ๋ฌ๋ ํํ์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ๊ถ์ฅ๋๋ฏ๋ก ํํ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ค์ต์ ์งํํ๋๋ก ํ๋ค.
security-context.xml์์ url์ ๋ฐ๋ผ ์ ๊ทผ ๊ถํ์ ๋ค๋ฅด๊ฒ ์ง์ ํ์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์๋ฒ๋ฅผ ๋๋ ค์ /all์ /member์ ์ ๊ทผํด๋ณด๋ฉด ๋ค๋ฅธ ์ํฉ์ด ์ผ์ด๋จ์ ํ์ธํ ์ ์๋ค.
/sample/all๋ก ์ ๊ทผํ ๊ฒฝ์ฐ
/sample/member๋ก ์ ๊ทผํ ๊ฒฝ์ฐ
/sample/member๋ ๋ก๊ทธ์ธํ์ด์ง(/login)๋ก ๊ฐ์ ์ด๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
(์ฐ๋ฆฌ๋ /login์ปจํธ๋กค๋ฌ๋ jsp๋ฅผ ์์ฑํด์ฃผ์ง ์์๋ค!๐ฎ)
์ด๋ก์จ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ๋๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ ์คํ๋ง ์ํ๋ฆฌํฐ๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ํ์ด์ง๋ผ๋ ์ ์ ์ ์ ์๋ค.
๊ทธ๋ฌ๋ ์์ง ์ฐ๋ฆฌ๋ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ์ ์ธ ์ค์ ์ ํตํด ์ง์ ํ ์์ด๋์ ํจ์ค์๋๋ก ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ ์ด์ด์ ์งํํด๋ณด๊ฒ ๋ค.
๋จ์ ๋ก๊ทธ์ธ ์ฒ๋ฆฌ
์คํ๋ง ์ํ๋ฆฌํฐ์์์ ์๋ฏธ ์ฐจ์ด
(์ผ๋ฐ์ ์ธ ์์คํ ์์์ ์๋ฏธ์ ๋ค๋ฅด๋ ์ฃผ์ํ ๊ฒ!)
username : ์ผ๋ฐ ์์คํ ์์์ userid์ ๊ฐ์ (!= ์ ์ ๋ช )
user : ์ธ์ฆ ์ ๋ณด์ ๊ถํ์ ๊ฐ์ง ๊ฐ์ฒด (!= ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ง ๊ฐ์ฒด)
ํ ์คํธ๋ฅผ ์ํด ๋จ์ํ ๋ก๊ทธ์ธ์ด ์ฒ๋ฆฌ๋๋ ๊ฒ์ ํ์ธํ๋ ค๊ณ ํ๋ค.
๋ฉ๋ชจ๋ฆฌ์์ ๋ฌธ์์ด์ ์ง์ ํ๊ณ ํด๋น ์์ด๋/ํจ์ค์๋๋ฅผ ์ ๋ ฅํ์์ ๋ ๋์ํ๋๋ก ์ค์ ํ๋ ์์ ์ ํ๋ค.
security-context.xml์ ์ฃผ์์ผ๋ก ํ์๋ ๋ถ๋ถ ์๋ ์ฝ๋๋ค์ ์์ ํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http>
<security:intercept-url pattern="/sample/all"
access="permitAll" />
<security:intercept-url
pattern="/sample/member" access="hasRole('ROLE_MEMBER')" />
<security:form-login />
</security:http>
<security:authentication-manager>
<!-- ์ถ๊ฐ๋ ๋ถ๋ถ -->
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}member"
authorities="ROLE_MEMBER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
user์ id๋ 'member'๋ก, password๋ 'member'๋ก ์ค ์ํฉ์ด๋ค.
authorities์์ฑ์๋ member์๊ฒ ์ฌ์ฉ์ ๊ถํ์ ์ฃผ์ด ๋ก๊ทธ์ธ์ด ๊ฐ๋ฅํ๋๋ก ์ค์ ํด์ฃผ์๋ค.
password์ {noop}์ ์คํ๋ง ์ํ๋ฆฌํฐ 5๋ฒ์ ๋ถํฐ ํ์์ ์ผ๋ก ์ฌ์ฉํด์ผ ํ๋ PasswordEncoder๋ฅผ ์ง์ ํ์ง ์์์ ๋ ์๋ฌ๊ฐ ๋๋ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํ ๋ฌธ์์ด์ด๋ค.
๋ญ... ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง PasswordEncoder๋ฅผ ์ง์ ํ์ง ์๊ณ ์์ ๋ฐฉํธ์ผ๋ก ํฌ๋งทํ ์ฒ๋ฆฌ๋ฅผ ์ง์ ํด์ ํจ์ค์๋ ์ธ์ฝ๋ฉ ๋ฐฉ์์ ์ง์ ํ ์ ์๋ค(5๋ฒ์ ์ ๊ฒฝ์ฐ)๋๋ฐ ํจ์ค์๋ ์ธ์ฝ๋ฉ ์ฒ๋ฆฌ์์ด ์ฌ์ฉํ๊ณ ์ถ์ ๋ ํจ์ค์๋ ์์ {noop}์ ์ถ๊ฐํ๋ฉด ๋๋ค๊ณ ํ๋ค. ๐คทโ๏ธ(?)
๋ค์ ์๋ฒ๋ฅผ ์คํํด์ (๋ค์ ์๋ฒ ์คํ ์ํด์ฃผ๋ฉด ์ ๋๋ก ๋์ํ์ง ์๋๋ค.)
/member๋ก ์ ๊ทผํ ๋ค, member/member๋ก ๋ก๊ทธ์ธํด์ฃผ๋ฉด ์๋์ ๊ฐ์ด /memberํ์ด์ง์ ์ ๊ทผํ ์ ์๊ฒ ๋๋ค.
๋ก๊ทธ์ธ์ ํ ๊ฒฝ์ฐ, ์ค๋ฅธ์ชฝ์ฒ๋ผ ๊ฐ๋ฐ์๋๊ตฌ์ Applicationํญ์ ํ์ธํด๋ณด๋ฉด Cookies์ 'JSESSIONID'์ ๊ฐ์ด ์ธ์ ์ ์ ์งํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ธ์ ์ฟ ํค์ ์กด์ฌ๋ฅผ ํ์ธํ ์ ์๋ค.
JSESSIONID = Tomcat์์ ๋ฐํํ๋ ์ฟ ํค ์ด๋ฆ ์ด๊ธฐ ๋๋ฌธ์ WAS๋ง๋ค ๋ค๋ฅธ ์ด๋ฆ์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์์๋์.
๋ก๊ทธ์์์ ํ๋ ๊ฒฝ์ฐ์๋ ํด๋น JSESSIONID์ฟ ํค๋ฅผ ๊ฐ์ ๋ก ์ญ์ ํ์ฌ ์ฒ๋ฆฌํ๋ค.
์ฌ๋ฌ ๊ถํ์ ๊ฐ์ง๋ ์ฌ์ฉ์ ์ค์
๊ด๋ฆฌ์๊ฐ์ด ์ผ๋ฐ์ฌ์ฉ์์ ๊ถํ๋ ๊ฐ์ง๊ณ , ๊ด๋ฆฌ์์ ๊ถํ๋ ๊ฐ์ง๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
๊ทธ๋ฐ ๊ฒฝ์ฐ 'ROLE_ADMIN'์ 'ROLE_MEMBER'๋ผ๋ 2๊ฐ์ ๊ถํ์ ๊ฐ์ง๋๋ก ์ง์ ํด์ค๋ค.
security-context.xml์ ์ฃผ์์ฒ๋ฆฌ ํด๋์ ๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http>
<security:intercept-url pattern="/sample/all"
access="permitAll" />
<security:intercept-url
pattern="/sample/member" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url
pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" /><!-- ์ถ๊ฐ๋ ๋ถ๋ถ -->
<security:form-login />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}member" authorities="ROLE_MEMBER"/>
<!-- ์ถ๊ฐ๋ ๋ถ๋ถ -->
<security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
์ถ๊ฐ๋ ๋ถ๋ถ์ ์ค๋ช ํ์๋ฉด..
<security:intercept-url pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" />
/sample/admin url์ ๋ํ ์ ๊ทผ์ ์ค์ ํจ
<security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN"/>
admin/admin์ผ๋ก ๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ 'ROLE_MEMBER'์ 'ROLE_ADMIN'๋ผ๋ 2๊ฐ์ ๊ถํ์ ๊ฐ์ง
์ด ๊ฒฝ์ฐ, admin์ /member์ /admin์ ๋ชจ๋ ์ ๊ทผํ ์ ์๋ค.
์ ๊ทผ ์ ํ ๋ฉ์์ง ์ฒ๋ฆฌ
'ROLE_MEMBER' ๊ถํ๋ง ๊ฐ์ง member์ฌ์ฉ์๊ฐ /adminํ์ด์ง์ ์ ๊ทผํ๋ ค๊ณ ํ๋ค๋ฉด 'ROLE_ADMIN'๊ถํ์ ๊ฐ์ง๊ณ ์์ง ์์ ์ ๊ทผ์ ์ ํ์ ๋ฐ์ ๊ฒ์ด๋ค.
ํด๋น ์ํฉ์ฒ๋ผ ์ ๊ทผ์ ์๋ํ๋ฉด ์๋์ ์ด๋ฏธ์ง์ฒ๋ผ Forbidden์๋ฌ๋ฅผ ๋ณด๊ฒ ๋๋ค.
member/member๋ก ๋ก๊ทธ์ธํ๊ณ /sample/admin url๋ก ์ ๊ทผํ ๊ฒฝ์ฐ
์คํ๋ง ์ํ๋ฆฌํฐ์์๋ ์ ๊ทผ ์ ํ์ ๋ํด์ ํน์ ํ URL๋ฅผ ์ง์ ํ๊ฑฐ๋ AccessDeniedHandler๋ฅผ ์ง์ ๊ตฌํํ ์ ์๋ค.
์ด ๊ฒฝ์ฐ <security:access-denied-handler>๋ฅผ security-context.xml์์ ์ฌ์ฉํ๋ค.
1) ํน์ ํ URL์ ์ง์ ํ๋ ๊ฒฝ์ฐ
error-page๋ฅผ ์ง์ ํด์ /accessError๋ผ๋ url๋ก ์ ๊ทผํ๋ ๊ฒฝ์ฐ ์ ๊ทผ ์ ํ ํ๋ฉด์ ์ฒ๋ฆฌํ๋ค.
security-context.xml์ ์ฃผ์์ฒ๋ฆฌ ํด๋์ ๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http auto-config="true" use-expressions="true"> <!-- ์ถ๊ฐ๋จ -->
<security:intercept-url pattern="/sample/all"
access="permitAll" />
<security:intercept-url
pattern="/sample/member" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url
pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" />
<security:form-login />
<security:access-denied-handler error-page="/accessError"/> <!-- ์ถ๊ฐ๋จ -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}member"
authorities="ROLE_MEMBER"/>
<security:user name="admin" password="{noop}admin"
authorities="ROLE_MEMBER, ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
<security:access-denied-handler>์ error-page์์ฑ์ /accessError url์ ์ง์ ํด์ฃผ์๋ค.
/accessError ์ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์ด์ฃผ๊ธฐ ์ํด CommonController.javaํ์ผ์ ์์ฑํ๋ค.
CommonController.java
package com.taeong.controller;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
public class CommonController { //๊ฐ๋จํ ์ฌ์ฉ์๊ฐ ์์๋ณผ ์ ์๋ ์๋ฌ๋ฉ์์ง๋ง์ Model์ ์ถ๊ฐ
@GetMapping("/accessError")
public void accessDenied(Authentication auth, Model model) {
//Authenticationํ์
์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋๋ก ์ค๊ณํด์ ํ์ํ ๊ฒฝ์ฐ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋๋ก ํจ
log.info("access Denied : "+auth);
model.addAttribute("msg","Access Denied");
}
}
accessError.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/security/tags"
prefix="sec"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Access Denied Page</h1>
<h2>
<c:out value="${SPRING_SECURITY_403_EXCEPTION.getMessage() }" />
</h2>
<h2>
<c:out value="${msg}" />
</h2>
</body>
</html>
Access Denied์ ๊ฒฝ์ฐ๋ 403 ์๋ฌ ๋ฉ์์ง๊ฐ ๋ฐ์ํ๋ค.
JSP์์๋ HttpServlet Request ์์ 'SPRING_SECURITY_403_EXCEPTION'์ด๋ผ๋ ์ด๋ฆ์ผ๋ก Access DeniedException ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋๋ค.
member/member๋ก ๋ก๊ทธ์ธํ ์ฌ์ฉ์๊ฐ /admin์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ, ์ด์ ์๋ Forbidden ์๋ฌ ํ๋ฉด์ด ๋ด์ง๋ง ํด๋น ์์ ์ ํตํด accessError.jsp์ ๋ด์ฉ์ด ๋ณด์ด๊ฒ ๋๋ค.
member/member๋ก ๋ก๊ทธ์ธํด์ adminํ์ด์ง์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ log์ฐฝ์์ ์๋์ ๊ฐ์ด ์ ๊ทผ์ ์๋ํ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค. (log.info("access Denied : "+auth); ๋ถ๋ถ)
INFO : com.taeong.controller.CommonController - access Denied : org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ff722209: Principal: org.springframework.security.core.userdetails.User@bfc28a9a: Username: member; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_MEMBER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffde5d4: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 71A6D88EE2BE6A8CCEEF15BC9B1A015D; Granted Authorities: ROLE_MEMBER
2) AccessDeniedHandler ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ธฐ
<security:access-denied-handler error-page="/accessError">๋ฅผ ์ฌ์ฉํ์ ๋๋ error-page๋ง์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์๊ฐ ์ ๊ทผํ๋ url์ ๋ณํ๊ฐ ์๊ธฐ์ง ์๋๋ค.
์์ ์ด๋ฏธ์ง๋ฅผ ๋ณด๋ฉด ๊ทธ๋๋ก /sample/admin์ ์์นํ๊ณ ์์ง๋ง ํ๋ฉด๋ง accessError.jsp์ ๋ด์ฉ๋ก ๋ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ ๊ทผ์ด ์ ํ๋ ๊ฒฝ์ฐ์ ๋ค์ํ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์ถ๋ค๋ฉด ์ง์ AccessDeniedHandler ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์ข๋ค.
์๋ก securityํจํค์ง๋ฅผ ์์ฑํ๊ณ (๋ด ๊ฒฝ์ฐ์๋ com.taeong.security๋ผ๋ ํจํค์ง๋ช ์ผ๋ก ์ฌ์ฉํ์๋ค.) CustomAccessDeniedHandler.java๋ฅผ ์ถ๊ฐํ์๋ค.
AccessDeniedHandler ์ธํฐํ์ด์ค๋ฅผ inplementsํด์ฃผ๊ณ ์ค๋ฒ๋ผ์ด๋ฉ์ผ๋ก AccessDeniedHandler์ ์ถ์๋ฉ์๋๋ค์ ๊ตฌํํด์ค๋ค.
CustomAccessDeniedHandler.java
package com.taeong.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import lombok.extern.log4j.Log4j;
@Log4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler{
//AccessDeniedHandler ์ธํฐํ์ด์ค๋ฅผ ์ง์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.error("Access Denied Handler");
log.error("Redirect....");
response.sendRedirect("/accessError");
}
}
security-context.xml์์๋ error-page์์ฑ ๋์ ์ CustomAccessDeniedHandler๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํด์ ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์๋์ ์ฝ๋๋ฅผ ์ฐธ์กฐํ์ฌ <bean>์ security-context.xml์ ์ถ๊ฐํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- ์ถ๊ฐ๋ ๋ถ๋ถ -->
<bean id="customAccessDenied" class="com.taeong.security.CustomAccessDeniedHandler"></bean>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/sample/all"
access="permitAll" />
<security:intercept-url
pattern="/sample/member" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url
pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" />
<security:form-login />
<!-- <security:access-denied-handler error-page="/accessError"/> --><!-- ์ญ์ ๋ ๋ถ๋ถ -->
<security:access-denied-handler ref="customAccessDenied"/><!-- ์ถ๊ฐ๋ ๋ถ๋ถ -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}member"
authorities="ROLE_MEMBER"/>
<security:user name="admin" password="{noop}admin"
authorities="ROLE_MEMBER, ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
์๋ฒ๋ฅผ ์ฌ์คํํ์ฌ member/member๋ก ๋ก๊ทธ์ธํ ๋ค /admin url๋ก ์ ๊ทผํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด accessError๋ก ๋ฆฌ๋ค์ด๋ ํธ ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋๊ธ