Web/Servlet && Spring

[Spring] 스프링 시큐리티 (spring security)

jinsiri 2019. 9. 24. 16:53

 대부분의 사용자 권한은 세션에 아이디 값을 저장하는 것으로 처리한다.

하지만 스프링 시큐리티를 이용하면 다음과 같은 작업들을 간편하게 처리할 수 있다.

- 로그인, 토큰 처리

- 암호화 처리

- 자동로그인

- JSP에서의 로그인 처리

 

스프링 시큐리티의 기본동작 방식은 필터와 인터셉터로 처리된다.

filter - 서블릿 자원

Interceptor - 스프링의 빈으로 관리되면서 스프링의 컨텍스트 내에 속한다.

 

사용방법

1. pom.xml 추가

<!-- 시큐리티 관련객체 -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

2. security-context.xml 생성

 spring- security를 설정할 때에는 5.0 에러가 발생하는 버그가 있으니 아래와 같이 버젼을 지운다.

<?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/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-context.xml -->
	<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>

3. web.xml 추가

	<!-- 스프링 시큐리티 필터 -->
	<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>
    
<-- ****************************************************************************** -->    
    <context-param>
		<param-name>contextConfigLocation</param-name>
		<!-- 공백을 구분자로 한다. -->
		<param-value>
		/WEB-INF/spring/root-context.xml
		/WEB-INF/spring/security-context.xml <--이부분을 추가
		</param-value>
	</context-param>

4. servlet-context 설정 추기

<!-- 인터셉터 설정 -->
	<beans:bean class="com.encore.interceptor.AuthInterceptor"
		id="authInterceptor"></beans:bean>
	<beans:bean class="com.encore.interceptor.LoginInterceptor"
		id="loginInterceptor"></beans:bean>

	<interceptors>
		<interceptor>
			<!-- interceptor가 가로채서 처리해 주세요. -->
			<mapping path="/sample/update" />
			<mapping path="/sample/delete" />

			<beans:ref bean="authInterceptor" />
		</interceptor>

		<interceptor>
			<mapping path="/sample/login" />
			<beans:ref bean="loginInterceptor" />
		</interceptor>
	</interceptors>

5. Sample2Controller.java

package com.encore.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.log4j.Log4j;

@Controller
@RequestMapping("/sample/*")
@Log4j
public class Sample2Controller {

	@GetMapping("/all")
	public void doAll() {
		System.out.println("모든 사용자가 접속할 수 있음");
	}

	@GetMapping("/member")
	public void doMember() {
		System.out.println("로그인된 사용자 접속할 수 있음");
	}

	@GetMapping("/admin")
	public void doAdmin() {
		System.out.println("관리자 접속할 수 있음");
	}

	@RequestMapping("/list")
	public void list() {
		System.out.println(">>>list");
	}

	@RequestMapping("/delete")
	public void delete() {
		System.out.println(">>>delete");
	}

	@RequestMapping("/update")
	public void update() {
		System.out.println(">>>update");
	}

	// ------------로그인
	@GetMapping("/login")
	public void loginForm() {

	}

	@PostMapping("/loginPost")
	public void loginPost(String username, String password, HttpSession session) {
		if (username.equals("siri") && password.equals("1234")) {
			session.setAttribute("login", "success");
			
		}
	}

}

6. AuthInterceptor.java 

package com.encore.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class AuthInterceptor extends HandlerInterceptorAdapter {

	private void saveDest(HttpServletRequest req) {
		String uri = req.getRequestURI();
		String query = req.getQueryString();
		System.out.println("uri>>>" + uri + ", query>>>" + query);
		// 192.168.0.96/sample/delete?id=1234

		if (query == null)
			query = "";
		else
			query = "?" + query;

		req.getSession().setAttribute("dest", uri + query);
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("========< 전처리 >==========");

		// 로그인 사용자 인증!! (만약, 로그인 하였다면 login키:success데이터)
		HttpSession session = request.getSession();
		Object login = session.getAttribute("login");

		if (login == null || !login.equals("success")) {
			saveDest(request);// 진행하려고 했던 URL을 세션에 저장!!
			response.sendRedirect("/sample/login");
			return false;
		}

		return true;
		// return true; -----> 매핑URL실행O (계속진행)
		// return false; -----> 매핑URL실행X (실행정지)
	}// 1.실행

	// 2.실행 ==> 매핑 URL (수정,삭제)

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("========< 후처리 >==========");
	}// 3.실행

}

7. LoginInterceptor.java

package com.encore.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class LoginInterceptor extends HandlerInterceptorAdapter {
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		HttpSession session = request.getSession();
		String login = (String) session.getAttribute("login");
		Object dest = session.getAttribute("dest");

		response.sendRedirect(dest != null ? (String) dest : "/board/list");
	}
}
반응형