일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- interrupted()
- ajax
- select
- 슈더코드
- this
- InterruptException
- this와 this() 차이
- map()
- function test
- 백준
- pseudo-code
- 마리아DB 쿼리 로그
- Bean LifecCycle
- 합배열
- 자바 람다식
- MariaDB Query Log
- 구간합구하기
- jquery
- @AllArgsConstructor
- 상속과 참조
- 백준 11659번
- 생성자
- 구간합
- @NoArgsConstructor
- 백준 1235번
- Java
- json
- SQL
- 2차원배열 구간합
- 백준 11660번
- Today
- Total
평범한 연구소
[Spring] 시큐리티 Security 본문
Spring Security
- 스프링 시큐리티는 Spring(and Spring Boot로 빌드된 애플리케이션) 웹 애플리케이션과 REST API를 보호하기 위해 널리 사용되는 프레임워크.
- REST API의 인증과 권한 부여를 제공. DB와 LDAP를 포함해 사용자 자격 증명을 위한 여러 소스와 잘 통합됨.
- 시큐리티는 애플리케이션을 구축할 때 중요한 비함수적 기능 중 하나.
Spring Security 요청 처리 절차
- 주로 서블릿 필터와 이들로 구성된 필터체인으로의 위임 모델을 사용한다. 서블릿 필터는 사용자의 요청을 가로채서 전 처리 하거나 서버의 응답을 가로채서 후처리를 할 수 있다.
- @MVC의 DIspatcherServlet이나 AOP를 이용해 프록시를 생성하지 않고 DelegatingFilterProxy 클래스를 사용한다. DelegatingFilterProxy를 이용하면서도 AOP 포인트 컷의 활용도 가능하다. DelegatingFilterProxy는 스프링 시큐리티에 정의된 필터로 HTTP 요청 필터링을 위임받아 처리한다.
- 스프링 시큐리티에서는 threadlocal 이라는 방식으로 사용자 정보를 저장한다. 스레드 로컬도 세션에서 보관 하지만 세션뿐만 아니라 다른 저장소를 이용할 수 있다.
REST API 시큐리티
- API 사용자는 누구일까?
- 사용자를 어떻게 식별할까 ?
- 사용자의 세부 정보를 어디에 저장할 수 있을까?
- 다른 종류의 사용자는 ?
- 각 유형의 사용자가 수행할 수 있는 작업은 무엇일까?
인증 (Authentication)
- 일반적으로 사용자 ID와 시크릿 번호를 사용해 사용자를 식별하는데, 이를 사용자 자격 증명이라고 한다.
- 사용자 자격 증명을 확인하고 API에 유효한 사용자인지 확인하는 과정이 인증이다.
- 유효한 사용자일까 ?
인증 (Authentication)의 종류
- 크리덴셜(Credential: 자격) 기반 인증
- 웹에서 사용하는 대부분의 인증 방식은 크리덴셜 기반 인증 방식이다. 즉, 권한을 부여받는데 한 차례의 인증 과정이 필요하며 주로 사용자명과 비밀번호를 입력 받아 저장된 비밀번호와 일치하는지 확인한다.
- 스프링 시큐리티에서는 아이디를 principle, 비밀번호를 credential 이라고 부른다.
- 이중 인증
- 한 번에 두 가지 방식으로 인증을 받는 것이다. 예를 들어 금융, 은행 웹 애플리케이션을 이용해 온라인 거래를 할 때에는 로그인과 보안인증서 두 가지 방법으로 인증 받는다. 인증(Authentication)이 하나 추가됨으로서 프로그래밍적으로 변화해야할 부분은 광범위해진다.
- 물리적인 인증
- 웹의 영역을 벗어난 것이지만 가장 효과적인 보안 수단 중 하나이다. 예를 들어 컴퓨터를 켤 때 지문을 인식 받거나 키를 삽입해야 하는 것들 이다.
권한 부여 (Authorization)
- 사용자를 인증한 후에는 어떤 종류의 작업을 수행할 수 있는지 결정해야한다.
- 널리 사용되는 옵션은 API와 연관된 여러 역할을 갖는 것이다. 역할과 관련된 다양한 API 작업에 권한을 가질 수 있다.
- 사용자에게 작업을 수행할 수 있는 권한이 있는지 확인하는 프로세스를 권한 부여 라고 한다.
- 알반적으로 권한은 역할(role) 형태로 승인된다.
- 유효한 사용자가 작업을 수행할 수 있을까 ?
권한 부여(Authorization)의 종류
- 부여된 권한 (Granted Autority)
- 적절한 절차로 사용자가 인증되었다면 권한을 부여해야한다. 회원가입 등을 통해 반영구적인 권한이 부여되었다면 이 회원에게 부여된 권한을 어딘가에 저장해야한다. 만약 해당 사용자가 로그인 했을 때 메인 페이지로 넘어갈 수 없다면 권한 부여에 문제가 있는 것이다.
- 리소스의 권한 (Intercept)
- 사용자의 권한만 있다고 보안이 제대로 동작하지 않는다. 보안이란, 원래 권한이 없는 이들이 원천적으로 리소스에 접근할 수 없도록 막아내는 것이다. 그런 의미에서 적절한 권한을 가진 이들만 해당 자원에 접근할 수 있도록 자원의 외부 요청을 원천적으로 가로채는 것(Intercept)이 웹 보안 이다.
스프링에서 제공하는 기본 권한 (Authority)
- ROLE_ANONYMOUS : 모든 사용자
- IS_AUTHENTICATED_ANONYMOUSLY : 익명 사용자
- IS_AUTHENTICATED_FULLY : 인증된 사용자
- IS_AUTHENTICATED_REMEMBERED : REMEMBERED 사용자
- ROLE_RESTRICTED : 제한된 사용자
- ROLE_USER : 일반 사용자
- ROLE_ADMIN : 관리자
스프링 시큐리티 활용 예제
Spring Security를 적용하기 위해 web.xml 설정
- <filter-name> 태그 값은 반드시 springSecurityFilterChain 이어야 한다.
- Spring Security는 자기 자신을 DelegatingFilterProxy와 연결하기 위해 springSecurityFilterChain 라는 필터 이름을 요구한다.
- 모든 요청 URL(/*) 에 DelegatingFilterProxy 필터를 적용하고 있다. DelegatingFilterProxy는 spring-security-context.xml을 통해 빈 중에서 이름이 springSecurityFilterChain인 빈을 참조하게 된다. 이렇게 DelegatingFilterProxy 와 Spring Security 가 연결된다.
<!-- 스프링 시큐리티 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml 의 contextConfigLocation 에서 정의된 security-context.xml 추가
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
...
/WEB-INF/spring/security-context.xml
</param-value>
</context-param>
security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 권한이 없는 페이지를 접근할 경우 접근 불가 메시지 출력 -->
<http auto-config="true">
<!-- spring 4.x에 추가된 옵션으로 ssl을 사용하지 않을 경우 csrf는 disalbed=true로 설정. -->
<csrf disabled="true"/>
<!-- 모든 유저 항상 승인 -->
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/index.jsp" access="permitAll"/>
<intercept-url pattern="/member/login" access="permitAll"/>
<intercept-url pattern="/resources/**" access="permitAll"/>
<!-- 하나의 권한 설정 -->
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<!-- 하나 이상의 권한 설정 -->
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<!-- 사용자 정의 로그인 폼 -->
<form-login login-page="/member/login"
login-processing-url="/member/login_check"
authentication-failure-url="/member/login_check?login_error"
username-parameter="userId"
password-parameter="userPwd"
default-target-url="/"
always-use-default-target="true"
/>
<logout logout-url="/member/logout"
invalidate-session="true"
logout-success-url="/"
/>
<!-- 접근 권한이 없는 경우 -->
<access-denied-handler error-page="/member/noAuthorized"/>
<!-- 동일 아이디로 1명만 접속(기존 세선 만료) -->
<session-management>
<concurrency-control max-sessions="1"/>
</session-management>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<!-- noop: 텍스트 그대로 패스워드를 인식! security 5.부터 -->
<user name="admin" password="{noop}admin" authorities="ROLE_ADMIN, ROLE_USER"/>
<user name="spring" password="{noop}spring" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
일반 사용자(spring)가 관리자 권한을 요구하는 기능을 실행할 때 접근 권한이 없으므로 noAuthorized.jsp 가 출력된다.
'Spring Framework' 카테고리의 다른 글
[Spring] excel 엑셀 다운로드 하기 (0) | 2022.12.21 |
---|---|
[Spring] JPA (Java Persistence API) (0) | 2022.12.07 |
[Spring] 웹스토리지(로컬 스토리지, 세션 스토리지) vs 쿠키 vs 세션 (0) | 2022.12.01 |
[Spring] 스프링에서 AJAX 사용하기 (@ResponseBody) (0) | 2022.11.17 |
[Spring] MVC (0) | 2022.11.13 |