BackEnd/Spring

SpringLegacyProject_SpringSecurity적용하기

Leo.K 2022. 7. 12. 16:18

오늘은 Spring Legacy Project에서 Spring Security를 적용해보기 위해 환경설정부터 간단한 실습을 진행해보도록 하겠다.

기본적으로 oracle, eclipse, tomcat, spring sts가 설치되어있다는 가정 하에 진행하겠다. 

먼저 Spring MVC 프로젝트를 생성해보자 .

 

패키지 네이밍 룰에 맞춰서 자유롭게 작성하도록 하자.

 

생성한 프로젝트를 우클릭하여 Run as -> Run on server를 클릭해서 등록한 톰캣으로 실행을 해주자. 실행을 하면 home.jsp가 실행되는데 아래의 코드를 추가하면 인코딩이 맞게 되어 한글이 깨지지 않는 결과가 나온다. 아래의 이미지를 보았다면 기본적인 프로젝트 셋팅은 완료되었다. 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

server.xml에서 path를 수정하자.

 

이제 Spring Security를 적용하기 위해서 Maven라이브러리를 pom.xml에 추가해보자. 현재 필자의 springframework버전은 5.0.0으로 spring security버전 또한 5.0.0으로 맞추어 주었다.

 

web.xml에 spring security를 위한 필터를 추가해주자. 필터의 이름은 springSecurityFilterChain으로 약속하고, 이것은 스프링 시큐리티 내부 빈으로써 자동 생성된다.

web.xml에 DispatcherServlet 설정 파일인 contextConfigLocation에 security-context.xml파일을 추가로 등록해주자.

 

다음으로, 스프링 시큐리티, 보안과 관련한 컨텍스트 파일을 따로 관리하기 위해 security-context.xml 파일을 만든다.

파일의 이름은 자유지만 security와 관련한 파일이기 때문에 가독성을 위해 security-context.xml로 정했다. 위치는 WEB-INF -> spring -> app servlet 우클릭 -> new -> spring bean configuration file을 생성한다.

파일을 생성했다면 아래와 같이 파일을 수정해주자. 가장 처음 namespace를 추가하여 진행했을 때는, 9행이 ~/spring-security.5.0.xsd라고 코딩 했더니 에러가 발생했었다. 이를 반드시 제거해야 한다. 

자세한 에러 해결방법은 아래 사이트를 참고하고 넘어가자

https://violet31.tistory.com/10

 

스프링 웹 시큐리티(Spring Web Security) xml 설정 관련 오류 해결법

security-context.xml 설정 시 네임스페이스에서 문제가 발생하는 경우 해결법 1. 에러 메세지 (Error Message) Multiple annotations found at this line: - You cannot use a spring-security-2.0.xsd or spring..

violet31.tistory.com

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
<?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:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/security 
                        http://www.springframework.org/schema/security/spring-security.xsd">
    
    
    <security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>
    </security:http>
    
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
               <security:user name="admin" password="1234" authorities="ROLE_USER, ROLE_ADMIN" />
               <security:user name="guest" password="1234" authorities="ROLE_USER" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans:beans>
 
cs

 

사실 위 처럼 코딩하면 에러가 발생한다. 이는 security의 버전이 올라가면서 보안이 강화된 탓인데, 이를 해결해주기 위해서는 password앞에 {noop}를 추가해주면 정상적으로 작동한다. 

에러 메세지 : java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

<security:http auto-config='true'> spring security가 기본 로그인 페이지를 제공해준다. 로그인 페이지를 개발자 입맛에 맞게 커스터마이징 할 수 있다.
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/> /**는 모든 디렉토리와 파일을 가라킨다. 즉, ROLE_ADMIN만 모든 디렉토리와 파일에 접근할 수 있는 권한을 가진다는 것이다.
<authentication-manager>  유저들의 권한을 설정한다. <user>태그의 authorities옵션은 해당 유저의 권한을 뜻한다. admin유저는 ROLE_USER와 ROLE_ADMIN권한을 갖고 있으며, guest는 ROLE_USER권한만 가지고 있다. 
기본적으로 권한을 설정할 때는, "ROLE_"를 접두어로 사용하고 규칙을 바꾸고 싶다면, <authentication-provider>태그 내에 role-prefix옵션을 통해 변경할 수 있다.

[ 커스터마이징 ]

접근 거부 페이지

1. 아래의 경로에 로그인 폴더를 만들고, 먼저 접근 거부 페이지를 생성하자.

WEB-INF - views - login

2. 컨트롤러를 만들자. 

src/main/java -> com.ict.security -> LoginController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ict.security;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
public class LoginController {
 
    @RequestMapping("/login/accessDenied.do")
    public String accessDenied() throws Exception{
        return "/login/accessDenied";
    }
}
 
cs

 

3. 권한이 없는 경우 403에러가 나오지 않도록 만들어 놓은 접근 거부 페이지를 등록한다.

 

서버를 재가동 해서 실행해보면 권한이 있는 admin은 왼쪽, 없는 guest는 오른쪽과 같은 결과가 나온다.

 

물론 security-context.xml에 등록해놓은 아이디 비밀번호와 다르다면 아래와 같은 결과가 나온다.

 

본격적으로 로그인 폼을 구현하기 전에 spring security관련 태그를 사용하기 위한 dependency를 추가한다.

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>5.0.0.RELEASE</version>
</dependency>
 
cs

 

부트스트랩에서 제공하는 무료 템플릿으로 사용하였다. 이제 컨트롤러에서 이 페이지를 불러올 수 있도록 매핑을 진행해보자. 

 

매핑이 끝났다면 최종적으로 아래와 같이 security-context.xml파일을 수정하자. 

hasRole('ROLE')
ROLE 권한을 가지고 있는 경우


hasAnyRole('ROLE1', 'ROLE2')
ROLE1, ROLE2 권한 중 하나라도 가지고 있는 경우


permitAll
모두 접근 가능


denyAll
모두 접근 불가능


inAnonymouse()
Anonymous 사용자일 경우


isRemeberMe()
Remember-me 기능으로 로그인한 사용자일 경우


isAuthenticated()
Anonymous 사용자가 아닌 경우


isFullyAuthenticated()
Anonymous 사용자가 아니고 Remeber-me 기능으로 로그인하지 않은 경우

<intercept-url /> : “/resouces/**”와 "/login/**" 경로는 접근 제한을 풀어주었다. resoruces에 있는 이미지 파일을 사용해야 하고, 로그인을 할 수 있도록 화면을 보여줘야 하기 때문이다.

<intercept-url> 태그를 사용할 때는 반드시 순서에 유의해야 한다. 가령 pattern="/**" 이 가장 맨 앞에 와버리면 모든 url이 "/**" 를 만족하기 때문에 누구나 접근이 가능해진다.

 

<form-login /> : 로그인 페이지를 커스텀할 수 있는 태그이다.

-login-page 속성에 앞서 만든 로그인 페이지의 url을 입력한다. 

-login-processing-url 속성은 loginPage.jsp를 만들 때, <form>태그의 action URL이. , login을 처리하는 부분이 따로 필요하지 않다.

-authentication-failure-url 속성은 로그인을 실패했을 때(아이디와 패스워드가 틀린 경우) 이동할 url이다. 본 예제에서는 로그인 페이지에 err파라미터를 true로 보냈다. 그리고 loginPage.jsp에서 jstl로 예외 처리하였습니다.

-default-target-url 속성은 로그인이 성공했을 때 이동하는 주소이다.

-username-parameterpassword-parameter는 로그인시 파라미터로 전달받을 이름을 정의한다. loginPage.jsp에서 정의한 로그인 아이디와 비밀번호를 입력받는 <input> 태그의 name과 일치해야 한다.

 

<session-management> : 세션 수를 설정하여 중복 로그인을 방지할 수 있다. 중복 로그인이 발생하는 경우 expired-url로 이동한다.

출처: https://shxrecord.tistory.com/162?category=662711 

'BackEnd > Spring' 카테고리의 다른 글

SpringBoot Day1  (0) 2022.08.10
SpringMVC_게시판_기능정리_국비  (0) 2022.07.15
Spring기초_Day6_웹 개발 모델  (0) 2022.07.11
Spring_Day5_SpringLifeCycle  (0) 2022.07.11
Spring_Transaction_국비_Day89  (0) 2022.07.08