스프링 MVC

준비중..

스프링 MVC

스프링을 사용한 웹서비스 만들기

13 스프링 시큐리티

# 스프링 시큐리티 ### 라이브러리 추가 라이브러리를 추가합니다. **스프링 버전**에 의존도가 있으므로 의존성(dependency) 관련 버전 확인 후 사용하세요. > **시큐리티 4.1.3**의 경우 요구되는 **스프링 버전은 4.3.2** 입니다. **pom.xml** ```xml <!-- Spring Security: web --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.1.3.RELEASE</version> </dependency> <!-- Spring Security: config --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.1.3.RELEASE</version> </dependency> <!-- Spring Security: taglibs --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>4.1.3.RELEASE</version> </dependency> ``` ### 설정파일 등록 스프링 시큐리티 설정파일을 등록합니다. **web.xml** ```xml <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/root-context.xml /WEB-INF/spring/security/security-context.xml </param-value> </context-param> ``` ### 필터 추가 스프링 시큐리티 적용을 위해 필터를 추가합니다. 필터의 이름은 반드시 `springSecurityFilterChanin`이어야 합니다. **web.xml** ```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> ``` ### 스프링 시큐리티 설정파일 스프링 시큐리티 관련 설정을 합니다. **/WEB-INF/spring/security/security-context.xml** ```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:sec="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"> <!-- 스프링 시큐리티 설정의 거의 모든 것 --> <sec:http pattern="/css/**" security="none" /> <sec:http pattern="/img/**" security="none" /> <sec:http pattern="/js/**" security="none" /> <sec:http pattern="/uploads/**" security="none" /> <sec:http auto-config='true' use-expressions="true"> <sec:intercept-url pattern="/" access="permitAll" /> <sec:intercept-url pattern="/login" access="permitAll" /> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> <sec:form-login login-page="/login" login-processing-url="/user/login" default-target-url="/" username-parameter="username" password-parameter="password" authentication-failure-url="/login?error" always-use-default-target='true' /> <sec:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login?logout" /> <!-- enable csrf protection --> <sec:csrf/> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <sec:user name="user" password="1234" authorities="ROLE_USER"/> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> </beans> ``` ### 로그인 페이지 생성 로그인 페이지를 만듭니다. **views/statics/login.jsp** ```jsp <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page pageEncoding="utf-8" %> <div class="jumbotron"> <h1>로그인</h1> </div> <form action="<c:url value='/user/login' />" method="post"> <div class="form-group form-group-lg"> <div class="form-group"> <label>사용자명</label> <input type="text" name="username" class="form-control" placeholder="이메일"> </div> <div class="form-group"> <label>비밀번호</label> <input type="password" name="password" class="form-control" placeholder="비밀번호"> </div> <div class="form-group"> <input type="hidden" name="${ _csrf.parameterName }" value="${ _csrf.token }" > </div> <div class="form-action"> <input type="submit" class="btn btn-primary btn-lg" value="로그인"> </div> </div> </form> ``` ### 로그인 / 로그아웃 버튼 추가 네비게이션에 로그아웃 버튼을 추가합니다. **tiles/components/header.jsp** ```jsp <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%> <%@ page pageEncoding="utf-8"%> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="#">Yes24</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"><a class="nav-link" href="#">도서<span class="sr-only">(current)</span></a></li> </ul> <!-- 로그인 버튼 --> <sec:authorize access="isAnonymous()"> <c:url var="loginUrl" value="/login" /> <ul class="nav navbar-nav navbar-right"> <li><a href="${ loginUrl }">로그인</a></li> </ul> </sec:authorize> <!-- 로그아웃 버튼 --> <sec:authorize access="isAuthenticated()"> <c:url var="logoutUrl" value="/logout" /> <form action="${logoutUrl}" method="post" class="navbar-form navbar-right"> <button type="submit" class="btn btn-default">로그아웃</button> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> </sec:authorize> </div> </nav> ``` ### 컨트롤러 생성 SessionsController.java ```java package com.mycompany.influencer; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class SessionsController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String login() { return "statics/login"; } } ``` 로그인 페이지 접속 확인 ![Imgur](https://i.imgur.com/bmENGj5.png) ### 테이블 생성 테이블명과 컬럼명은 기본적으로 지정하여 사용(필요시 커스터마이징 가능) ``` create table users ( id serial primary key, email varchar(50) unique, password varchar(100), enabled boolean not null ); insert into users (email, password, enabled) values('[email protected]', '1234', true); ``` ``` create table authorities ( email varchar(50) not null, authority varchar(50) not null ); insert into authorities (email, authority) values('[email protected]', 'USER'); ``` ### 시큐리티 설정 사용자 인증을 DB로부터 받아오도록 함. 사용자 및 권한 관련 쿼리를 커스터마이징(기본값으로 users테이블은 username과 password를 컬럼값으로 사용하나 위에서 email과 password를 사용하였으므로 쿼리변경 필수!!) **spring/security/security-context.xml** ```xml <sec:authentication-manager> <sec:authentication-provider> <sec:jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT email, password, enabled FROM users WHERE email = ?" authorities-by-username-query="SELECT email, authority FROM authorities WHERE email = ?" /> </sec:authentication-provider> </sec:authentication-manager> ``` ```xml <sec:form-login login-page="/login" login-processing-url="/user/login" default-target-url="/" username-parameter="email" password-parameter="password" authentication-failure-url="/login?error" always-use-default-target='true' /> ``` ### 로그인 페이지 로그인 페이지 폼 데이터의 이름 또한 컬럼명에 맞게 변경 **views/statics/login.jsp** ```jsp <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ page pageEncoding="utf-8"%> <div class="jumbotron"> <h1>로그인</h1> </div> <div class="container"> <form action="<c:url value='/user/login' />" method="post"> <div class="form-group form-group-lg"> <div class="form-group"> <label>사용자명</label> <input type="text" name="email" class="form-control" placeholder="이메일"> </div> <div class="form-group"> <label>비밀번호</label> <input type="password" name="password" class="form-control" placeholder="비밀번호"> </div> <div class="form-group"> <input type="hidden" name="${ _csrf.parameterName }" value="${ _csrf.token }"> </div> <div class="form-action"> <input type="submit" class="btn btn-primary btn-lg" value="로그인"> </div> </div> </form> </div> ```