일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 참조형변수
- oracle
- 대덕인재개발원
- 다형성
- exception
- 자바
- 집합_SET
- 오라클
- 사용자예외클래스생성
- 예외처리
- NestedFor
- 컬렉션프레임워크
- 어윈 사용법
- 예외미루기
- 한국건설관리시스템
- 컬렉션 타입
- cursor문
- 자동차수리시스템
- EnhancedFor
- 메소드오버로딩
- GRANT VIEW
- 인터페이스
- 환경설정
- 객체 비교
- Java
- 정수형타입
- 추상메서드
- 제네릭
- 생성자오버로드
- abstract
- Today
- Total
거니의 velog
231211_SPRING 2 (14-1) 본문
[pom.xml]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kr.or</groupId>
<artifactId>ddit</artifactId>
<name>SecurityTest</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.3.25</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
[web.xml]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--
한글 처리를 위한 UTF-8 필터 등록
JSP나 서블릿 처리할 때마다 넘겨받은 request를 setCharacterEncoding으로 UTF-8 설정했던 부분을 필터로 대체함
-->
<filter>
<filter-name>encordingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encordingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- http://localhost/
package kr.or.ddit.controller;
public class SecurityController {
/*
* [ 18장 : 스프링 시큐리티 ]
*
* 1. 스프링 시큐리티 소개
*
* - 애플리케이션에서 보안 기능을 구현하는데 사용되는 프레임워크이다.
* - 스프링 시큐리티는 필터 기반으로 동작하기 때문에 스프링 MVC와 분리되어 동작한다.
*
* # 기본 보안 기능
* - 인증 (Authentocation)
* > 애플리케이션 사용자의 정당성을 확인한다.
*
* - 인가 (Authorization)
* > 애플리케이션의 리소스나 처리에 대한 접근을 제어한다.
*
* # 시큐리티 제공 기능
* - 세션 관리
* - 로그인 처리
* - CSRF 토큰 처리
* - 암호화 처리
* - 자동 로그인
*
* *** CSRF 용어 설명
* - 크로스 사이트 요청 위조는 웹 사이트 취약점 공격의 하나로, 사용자가 자신의 의지와는 무관하기 공격자가
* 의도한 행위(수정, 삭제, 등록 등)를 특정 웹 사이트에 요청하게 하는 공격을 말한다.
*
* > CSRF 공격을 대비하기 위해서는 스프링 시큐리티 CSRF Token을 이용하여 인증을 진행한다.
*
* # 시큐리티 인증 구조
*
* 클라이언트에서 타겟으로 들어가기 위해서 요청을 진행한다. 이 때 타겟에 설정되어 있는 요청 접근 권한이 '사용자'
* 등급일 때로 설정되어 있다고 가정하자. 타겟으로 접근하기 위한 요청을 날렸고 요청 안에 사용자 등급에 해당하는 인가
* 정보가 포함되어 있지 않으면 스프링 시큐리티는 인증을 진행할 수 있도록 인증 페이지(로그인 페이지)를 제공하여
* 사용자에게 인증을 요청한다. 사용자는 아이디, 비밀번호를 입력 후 인증을 요청한다.
* 클라이언트에서 서버로 요청한 HttpServletRequest의 요청 객체를 AuthenticationFilter가 요청을
* 인터셉터 하는데, UsernamePasswordAuthenticationToken을 통해 인증을 진행할 토큰을 만들어
* AuthenticationManager에게 위임한다. 넘겨 받은 id, pw를 이용해 인증을 진행하는 데 성공시,
* Authentication 객체 생성과 성공을 전달하고, 그렇지 않으면 Exception 에러를 발생시킨다.
* 인증에 성공 후, 만들어진 Authentication 객체를 AuthenticationProvider에게 전달하고
* UserDetailService에게 넘겨받은 Authentication 객체 정보를 이용해서 Database에 일치하는 회원 정보
* 를 조회하여 꺼낸다. 꺼낸 정보를 UserDetails로 만들고 최종 User 객체에 회원 정보를 등록한다.
* 등록이 되면서 User Session 정보가 생성된다. 이후 스프링 시큐리티 내 SecurityContextHolder
* (시큐리티 인메모리)에 UserDetail 정보를 저장한다. 그리고 최종적으로 JSESSIONID가 유효한지를 검증 후
* 인증을 완료 후 타겟 정보로 넘어가도록 돕는다.
*
* 2. 스프링 시큐리티 설정
*
* # 환경 설정
* - 의존 라이브러리 설정(pom.xml 설정)
* > spring-security-web
* > spring-security-config
* > spring-security-core
* > spring-security-taglibs
*
* # 웹 컨테이너 설정(web.xml)
* - 스프링 시큐리티가 제공하는 서블릿 필터 클래스를 서블릿 컨테이너에 등록하나.
* - 스프링 시큐리티는 필터 기반이므로 시큐리티 필터체인을 등록한다.
* > context-param의 param-value 추가
* (추가 파라미터: /WEB-INF/spring/security-context.xml)
* > SpringSecurityFilterChain 추가
*
* # 스프링 시큐리티 설정
*
* - 스프링 시큐리티 컴포넌트를 빈으로 정의한다.
* - spring/security-context.xml 설정
*
* # 웹 화면 접근 정책
*
* - 웹 화면 접근 정책을 정한다. (테스트를 위한 각 화면 당 접근 정책을 설정한다.)
*
* 대상 | 화면 | 접근 정책
* ------------------------------------------------------------
* 일반 게시판 | 목록 화면 | 모두가 접근 가능하다.
* | 등록 화면 | 로그인한 회원만 접근 가능하다.
* ------------------------------------------------------------
* 공지사항 게시판 | 목록 화면 | 모두가 접근 가능하다
* | 등록 화면 | 로그인한 관리자만 접근 가능하다.
* ------------------------------------------------------------
*
* # 화면 설명
* - 컨트롤러
* > controller/SecurityBoardController
* > controller/SecurityNoticeController
*
* - 화면
* > board/list, register
* > notice/list, register
*
* 3. 접근 제한 설정
*
* - 시큐리티 설정을 통해서 특정 URI에 접근을 제한할 수 있다.
*
* # 환경 설정
*
* - 스프링 시큐리티 설정
* > URI 패턴으로 접근 제한을 설정한다.
* > security-context.xml 설정
* <security:intercept-uri pattern="/board/list" access="permitAll" />
* <security:intercept-uri pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
* > notice도 마찬가지로 설정...
*
* # 화면 설명
* - 일반 게시판 목록 화면(모두 접근 가능하도록 되어 있음 : permitAll)
* - 일반 게시판 등록 화면(회원 권한을 가진 사용자만 접근 가능 : hasRole('ROLE_MEMBER'))
* > 접근 제한에 걸려 스프링 시큐리티가 기본적으로 제공하는 로그인 페이지로 이동한다.
* - 공지사항 게시판 목록 화면(모두 접근 가능하도록 되어 있음 : permitAll)
* - 공지사항 게시판 등록 화면(관리자 권한을 가진 사용자만 접근 가능 : hasRole('ROLE_ADMIN'))
* > 접근 제한에 걸려 스프링 시큐리티가 기본적으로 제공하는 로그인 페이지로 이동한다.
*
* 4. 로그인 처리
*
* - 메모리 상에 아이디와 패스워드를 지정하고 로그인을 처리한다.
* - 스프링 시큐리티 5버전부터는 패스워드 암호화 처리기를 반드시 이용하도록 변경 되었다.
* - 암호화 처리기를 사용하지 않도록 "{noop}" 문자열을 비밀번호 앞에 사용한다.
*
* # 환경 설정
*
* - 스프링 시큐리티 설정
* > security-context.xml 설정
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
*
* # 화면 설명
*
* - 일반 게시판 등록 화면
* > 접근 제한에 걸려 스프링 시큐리티가 기본적으로 제공하는 로그인 페이지가 연결되고,
* 일반 회원 등급인 ROLE_MEMBER 권한을 가진 member 계정으로 로그인 후 해당 페이지로 접근 가능.
* - 공지사항 게시판 등록 화면
* > 접근 제한에 걸려 스프링 시큐리티가 기본적으로 제공하는 로그인 페이지가 연결되고,
* 관리자 등급인 ROLE_ADMIN 권한을 가진 admin 계정으로 로그인 후 해당 페이지로 접근 가능.
*
* 5. 접근 거부 처리
*
* - 접근 거부가 발생한 상황을 처리하는 접근 거부 처리자의 URI를 지정할 수 있다.
*
* # 환경 설정
*
* - 스프링 웹 설정(servlet-context.xml 설정)
* > <context:component-scan base-package="kr.or.ddit.security..." />
* ** 필요에 의한 패키지 라인을 bean으로 등록하여 사용해야 할 때 스프링 웹 설정에서 base-package를 설정할 수 있다.
*
* - 스프링 시큐리티 설정(security-context.xml 설정)
* > 접근 거부 처리자의 URI를 지정
* > <security:access-denied-handler error-page="/accessError/" />
*
* # 접근 거부 처리
*
* - 접근 거부 처리 컨트롤러 작성
* > security/CommonController
*
* # 화면 설명
* - 일반 게시판 등록 페이지
* > 접근 제한에 걸려 스프링 시큐리티가 제공하는 로그인 페이지가 나타나고, 회원 권한을 가진 계정으로
* 접근 시 접근 가능
* - 공지사항 게시판 등록 페이지
* > 접근 제한에 걸려 스프링 시큐리티가 제공하는 로그인 페이지가 나타나고, 회원 권한을 가진 계정으로
* 접근 시에 공지사항 게시판 등록 페이지는 관리자 권한으로만 접근 가능하므로 접근이 거부된다.
* 이 때, access-denied-handler로 설정되어 있는 URI로 이동하고 해당 페이지에서 접근이
* 거부 되었을 떄 보여질 페이지의 정보가 나타난다.
*
* 6. 사용자 정의 접근 거부 처리자
*
* - 접근 거부가 발생한 상황에 단순 메시지 처리 이상의 다양한 처리를 하고 싶다면 AccessDeniedHandler를 직접 구현한다.
*
* # 환경 설정
* - 스프링 시큐리티 설정(security-context.xml 설정)
* > id가 'customAccessDenied'를 가진 빈을 등록한다.
* > <security:access-denied-handler ref="customAccessDenied" />
*
* # 접근 거부 처리자 클래스 정의
* - CustomAccessDeniedHandler 클래스 정의
* > AccessDeniedHandler 인터페이스를 참조받아서 handle 메소드를 재정의하여 사용한다.
* 우리는 접근이 거부되었을 때 빈으로 등록해 둔 CustomAccessDeniedHandler 클래스가 발동해 해당 메소드가
* 실행되고 response 내장 객체를 활용하여 /accessError URL로 이동하여 접근 거부시 보여질 페이지로 이동하지만
* 이곳에서 더 많은 로직을 처리할 수도 있다. (request, response 내장 객체를 이용하여 다양한 처리 가능)
*
* # 화면 설명
* - 일반 게시판 등록 페이지
* > 접근 제한에 걸려 스프링 시큐리티가 제공하는 로그인 페이지가 나타나고, 회원 권한을 가진 계정으로 접근 시 접근 가능
* - 공지사항 게시판 등록 페이지
* > 접근 제한에 걸려 스프링 시큐리티가 제공하는 로그인 페이지가 나타나고, 회원 권한을 가진 계정으로 접근 시에 공지사항
* 게시판 등록 페이지는 관리자 권한만 접근 가능하므로 접근이 거부된다. 이 때, access-denied-handler로 설정
* 되어 있는 ref 속성에 부여된 클래스 메소드로 이동하고 해당 페이지에서 접근이 거부되었을 때 페이지의 정보가 나타난다.
*
* 7. 사용자 정의 로그인 페이지
*
* - 기본 로그인 페이지가 아닌 사용자가 직접 정의한 로그인 페이지를 사용한다.
*
* # 환경 설정
* - 스프링 시큐리티 설정(security-context.xml 설정)
*
* <security:form-login login-page="/login" /> 설정
* : 사용자가 직접 만든 로그인 페이지로 이동할 '/login' URL을 가지고 있는 컨트롤러 메소드를 정의
*
* # 로그인 페이지 정의
*
* - 사용자가 정의한 로그인 컨트롤러
* > controller 패키지 안에 LoginController 생성
* - 사용자가 정의한 로그인 뷰
* > views/loginForm.jsp
*
* ** 시큐리티에서 제공하는 기본 로그인 페이지로 이동하지 않고, 사용자가 정의한 로그인 페이지의 URI를 요청하여
* 해당 페이지에서 권한을 체크하도록 한다. 인증이 완료되면 최초의 요청된 target URI로 이동한다.
* 그렇지 않은 경우 사용자가 만들어놓은 접근 거부 페이지로 이동한다.
*
* 8. 로그인 성공 처리
*
* - 로그인을 성공한 후에 로그인 이력 로그를 기록하는 등의 동적을 하고 싶은 경우가 있다.
* 이런 경우 AuthenticationSuccessHandler라는 인터페이스를 구현해서 로그인 성공 처리자로 지정할 수 있다.
*
* # 환경 설정
* - customLoginSuccess Bean 등록
* <security:form-login login-page="/login" authentication-success-handler-ref="customLoginSuccess" />
*
* # 로그인 성공 처리자 클래스 정의
* - 로그인 성공 처리자
* > SavedRequestAwareAuthenticationSuccessHandler는 AuthenticationSuccessHandler의 구현 클래스이다.
* 인증 전에 접근을 시도한 URL로 리다이렉트하는 기능을 가지고 있으며 스프링 시큐리티에서 기본적으로
* 사용되는 구현 클래스이다.
* - 로그인 성공 처리자2
* > AuthenticationSuccessHandler 인터페이스를 직접 구현하여 인증 전에 접근을 시도한 URL로
* 리다이렉트하는 기능을 구현한다.
*
* # 화면 설명
* - 일반 게시판 등록 화면
* > 사용자가 정의한 로그인 페이지에서 회원 권한에 해당하는 계정으로 로그인 시, 성공했다면 성공 처리자인
* CustomLoginSuccess 클래스로 넘어가 넘겨받은 파라미터들 중 authentication 안에
* principal로 User 정보를 받아서 username과 password를 출력한다.
* (출력 정보는 로그인 성공 시 인증된 회원 정보이다.)
*
* 9. 로그아웃 처리
*
* - 로그아웃을 위한 URI를 지정하고, 로그아웃 처리 후에 별도의 작업을 하기 위해서 사용자가 직접 구현한 처리자를
* 등록할 수 있다.
*
* # 환경 설정
*
* - 스프링 시큐리티 설정(security-context.xml 설정)
* > <security:logout logout-url="/logout" invalidate-session="true" />
*
* ** logout 경로를 스프링에서 제공하는 /logout 경로로 설정한다.
* logout 처리 페이지에서도 action 경로를 /logout으로 설정한다.
*/
}
* 우리가 시큐리티 적용 상태에서 특정 타겟 요청 시, 타겟은 곧 보호자원에 해당하는 권한이 걸려 있을 것이다. 예를 들어, 내가 가고자 하는 타겟이 ROLE_MEMBER에 해당하는 회원만 들어가는 권한으로 묶여 있다면, 이 타겟 진입시 해당 요청을 서블릿 필터 체인에 진입한다. 여기에는 무수히 많은 필터가 있는데, 그 중에 로그인이라는 인증 절차를 거칠 것. JSP에서 어떤 페이지가 나타났었는가? 로그인 화면을 보여 줌.
* 그 로그인 페이지를 던져주는 녀석도 필터 체인임. 내가 보낸 요청을 필터 체인이 받음. 프록시도 필터 체인에 포함. 로그인을 담당하는 친구를 필터 기반으로 볼 것.
이 사진은 스프링 시큐리티의 아키텍처 사진이고 스프링 시큐리티의 흐름은 아래와 같다.
-----------------------------------------------------------------------
1. Http Request 수신
-> 사용자가 로그인 정보와 함께 인증 요청을 한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
2. 유저 자격을 기반으로 인증토큰 생성
-> AuthenticationFilter가 요청을 가로채고, 가로챈 정보를 통해 UsernamePasswordAuthenticationToken의 인증용 객체를 생성한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
3. FIlter를 통해 AuthenticationToken을 AuthenticationManager로 위임
-> AuthenticationManager의 구현체인 ProviderManager에게 생성한 UsernamePasswordToken 객체를 전달한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
4. AuthenticationProvider의 목록으로 인증을 시도
-> AutenticationManger는 등록된 AuthenticationProvider들을 조회하며 인증을 요구한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
5. UserDetailsService의 요구
-> 실제 데이터베이스에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보를 넘겨준다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
6. UserDetails를 이용해 User객체에 대한 정보 탐색
-> 넘겨받은 사용자 정보를 통해 데이터베이스에서 찾아낸 사용자 정보인 UserDetails 객체를 만든다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
7. User 객체의 정보들을 UserDetails가 UserDetailsService(LoginService)로 전달
-> AuthenticaitonProvider들은 UserDetails를 넘겨받고 사용자 정보를 비교한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
8. 인증 객체 or AuthenticationException
-> 인증이 완료가되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환한다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
9. 인증 끝
-> 다시 최초의 AuthenticationFilter에 Authentication 객체가 반환된다.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
10. SecurityContext에 인증 객체를 설정
-> Authentication 객체를 Security Context에 저장한다.
-----------------------------------------------------------------------
최종적으로는 SecurityContextHolder는 세션 영역에 있는 SecurityContext에 Authentication 객체를 저장한다. 사용자 정보를 저장한다는 것은 스프링 시큐리티가 전통적인 세선-쿠키 기반의 인증 방식을 사용한다는 것을 의미한다.
[pom.xml]
<!-- 스프링 시큐리티 라이브러리 의존 관계 정의 시작 -->
<!-- 스프링 시큐리티를 웹에서 동작하도록 해줌 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 스프링 시큐리티 설정을 도와줌 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 스프링 시큐리티 일반 기능 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 스프링 시큐리티 태그 라이브러리를 연결해 줌 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 스프링 시큐리티 라이브러리 의존 관계 정의 끝 -->
[web.xml]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<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>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--
한글 처리를 위한 UTF-8 필터 등록
JSP나 서블릿 처리할 때마다 넘겨받은 request를 setCharacterEncoding으로 UTF-8 설정했던 부분을 필터로 대체함
-->
<filter>
<filter-name>encordingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encordingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 서블릿 필터 클래스를 서블릿 컨테이너에 등록함 -->
<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-app>
<?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:form-login />
</security:http>
<security:authentication-manager>
</security:authentication-manager>
</beans>
package kr.or.ddit.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/board")
public class BoardController {
private static final Logger log = LoggerFactory.getLogger(BoardController.class);
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list() {
log.info("list : access to all");
return "board/list";
}
@RequestMapping(value = "/register", method = RequestMethod.GET)
public String register() {
log.info("register : access to member");
return "board/register";
}
}
package kr.or.ddit.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/notice")
public class NoticeController {
private static final Logger log = LoggerFactory.getLogger(NoticeController.class);
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list() {
log.info("list : access to all");
return "notice/list";
}
@RequestMapping(value = "/register", method = RequestMethod.GET)
public String register() {
log.info("register : access to admin");
return "notice/register";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>BOARD LIST</title>
</head>
<body>
<h3>BOARD LIST : access to all</h3>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>BOARD REGISTER</title>
</head>
<body>
<h3>BOARD REGISTER : access to member</h3>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>NOTICE LIST</title>
</head>
<body>
<h3>NOTICE LIST : access to all</h3>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>NOTICE REGISTER</title>
</head>
<body>
<h3>NOTICE REGISTER : access to admin</h3>
</body>
</html>
- http://localhost/board/list
- http://localhost/board/register
- http://localhost/notice/list
- http://localhost/notice/register
[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>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!-- 폼 기반 인증 기능을 사용한다. -->
<security:form-login />
</security:http>
<security:authentication-manager>
</security:authentication-manager>
</beans>
- http://localhost/notice/list
- http://localhost/notice/register
- http://localhost/board/list
- http://localhost/board/register
[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>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!-- 폼 기반 인증 기능을 사용한다. -->
<security:form-login />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
- http://localhost/board/register
- http://localhost/notice/register
[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>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!-- 폼 기반 인증 기능을 사용한다. -->
<security:form-login />
<!-- 5. 접근 거부 처리자 : 접근 거부 처리자의 URI를 지정 -->
<security:access-denied-handler error-page="/accessError" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package kr.or.ddit.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class CommonController {
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@RequestMapping(value = "/accessError")
public String accessDenied(Authentication auth, Model model) {
log.info("Access Denied : " + auth);
model.addAttribute("msg", "Access Denied");
return "accessError";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ACCESS ERROR</title>
</head>
<body>
<h3>Access Denied</h3>
<!--
SPRING-SECURITY_403-EXCEPTION.message 는 'Access is denied' 문자열을 출력한다.
security-context.xml에서 security:access-denied-handler 태그 자체로 설정했을 때 메세지가 출력
-->
<h2>${SPRING-SECURITY_403-EXCEPTION.message }</h2>
<h2>${msg }</h2>
</body>
</html>
- http://localhost/board/register
- http://localhost/notice/register
[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">
<!-- 6. 사용자 정의 접근 거부 처리자 Bean 추가 -->
<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<security:http>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!-- 폼 기반 인증 기능을 사용한다. -->
<security:form-login />
<!-- 5. 접근 거부 처리자 : 접근 거부 처리자의 URI를 지정 -->
<!-- <security:access-denied-handler error-page="/accessError" /> -->
<!-- 6. 사용자 정의 접근 거부 처리자 추가 : customAccessDenied를 접근 거부 처리자로 등록 -->
<security:access-denied-handler ref="customAccessDenied" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package kr.or.ddit.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private static final Logger log = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.info("CustomAccessDeniedHandler handle() 실행...!");
// CommonController에서 만들어둔 컨트롤러 메소드를 실행한다.
response.sendRedirect("/accessError");
}
}
- http://localhost/board/register
- http://localhost/notice/register
[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">
<!-- 6. 사용자 정의 접근 거부 처리자 Bean 추가 -->
<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<security:http>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!-- 폼 기반 인증 기능을 사용한다. : 사용자 정의 로그인 페이지 추가(login-page) -->
<security:form-login login-page="/login" />
<!-- 5. 접근 거부 처리자 : 접근 거부 처리자의 URI를 지정 -->
<!-- <security:access-denied-handler error-page="/accessError" /> -->
<!-- 6. 사용자 정의 접근 거부 처리자 추가 : customAccessDenied를 접근 거부 처리자로 등록 -->
<security:access-denied-handler ref="customAccessDenied" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package kr.or.ddit.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
private static final Logger log = LoggerFactory.getLogger(LoginController.class);
// 사용자가 정의한 로그인 페이지를 요청할 컨트롤러 메소드
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginForm(String error, String logout, Model model) {
log.info("error : " + error);
log.info("logout : " + logout);
if(error != null) {
model.addAttribute("error", "Login Error!");
}
if(logout != null) {
model.addAttribute("logout", "Logout!");
}
return "loginForm";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LOGIN FORM</title>
</head>
<body>
<h1>Login</h1>
<h2>${error }</h2> <!-- 에러 발생 시, 출력할 메세지 -->
<h2>${logout }</h2> <!-- 로그아웃 발생 시, 출력할 메세지 -->
<!-- security를 적용 후 데이터를 전송 시 csrfInput으로 시큐리티 토큰을 전송해야 한다. -->
<form action="/login" method="post">
username : <input type="text" name="username" /><br />
password : <input type="text" name="password" /><br />
<button type="submit">로그인</button>
<sec:csrfInput />
</form>
</body>
</html>
- http://localhost/board/register
[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">
<!-- 6. 사용자 정의 접근 거부 처리자 Bean 추가 -->
<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
<security:http>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!--
폼 기반 인증 기능을 사용한다. : 사용자 정의 로그인 페이지 추가(login-page),
로그인 성공 처리 추가 : 로그인 성공 후 처리를 담당하는 처리자로 지정(customLoginSuccess)
-->
<security:form-login login-page="/login" authentication-success-handler-ref="customLoginSuccess" />
<!-- 5. 접근 거부 처리자 : 접근 거부 처리자의 URI를 지정 -->
<!-- <security:access-denied-handler error-page="/accessError" /> -->
<!-- 6. 사용자 정의 접근 거부 처리자 추가 : customAccessDenied를 접근 거부 처리자로 등록 -->
<security:access-denied-handler ref="customAccessDenied" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package kr.or.ddit.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
private static final Logger log = LoggerFactory.getLogger(CustomLoginSuccessHandler.class);
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
log.info("onAuthenticationSuccess() 실행...!");
User user = (User) authentication.getPrincipal();
log.info("username : " + user.getUsername());
log.info("password : " + user.getPassword());
clearAuthenticationAttribute(request);
SavedRequest savedRequest = requestCache.getRequest(request, response);
String targetUrl = savedRequest.getRedirectUrl();
log.info("Login Success targetUrl : " + targetUrl);
response.sendRedirect(targetUrl);
}
private void clearAuthenticationAttribute(HttpServletRequest request) {
// session 가 존재한다면 현재 session을 반환하고, 그렇지 않으면 null을 반환한다.
HttpSession session = request.getSession(false);
if(session == null) {
return;
}
// SPRING_SECURITY_LAST_EXCEPTION 값을 세션에서 삭제
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
}
- http://localhost/board/register
[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">
<!-- 6. 사용자 정의 접근 거부 처리자 Bean 추가 -->
<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
<security:http>
<!-- 3. 접근 제한 설정 : URL 패턴으로 접근 제한을 설정한다. -->
<security:intercept-url pattern="/board/list" access="permitAll" />
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
<!-- 3. 접근 제한 설정 끝 -->
<!--
폼 기반 인증 기능을 사용한다. : 사용자 정의 로그인 페이지 추가(login-page),
로그인 성공 처리 추가 : 로그인 성공 후 처리를 담당하는 처리자로 지정(customLoginSuccess)
-->
<security:form-login login-page="/login" authentication-success-handler-ref="customLoginSuccess" />
<!-- 5. 접근 거부 처리자 : 접근 거부 처리자의 URI를 지정 -->
<!-- <security:access-denied-handler error-page="/accessError" /> -->
<!-- 6. 사용자 정의 접근 거부 처리자 추가 : customAccessDenied를 접근 거부 처리자로 등록 -->
<security:access-denied-handler ref="customAccessDenied" />
<!-- 9. 로그아웃 처리 : 로그아웃 처리를 위한 URI를 지정하고, 로그아웃한 후에 세션을 무효화한다. -->
<security:logout logout-url="/logout" invalidate-session="true" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER" />
<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package kr.or.ddit.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
private static final Logger log = LoggerFactory.getLogger(LoginController.class);
// 사용자가 정의한 로그인 페이지를 요청할 컨트롤러 메소드
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginForm(String error, String logout, Model model) {
log.info("error : " + error);
log.info("logout : " + logout);
if(error != null) {
model.addAttribute("error", "Login Error!");
}
if(logout != null) {
model.addAttribute("logout", "Logout!");
}
return "loginForm";
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logoutForm() {
return "logoutForm";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LOGOUT FORM</title>
</head>
<body>
<h2>Logout Form</h2>
<form action="/logout" method="post">
<input type="submit" value="로그아웃" />
<sec:csrfInput />
</form>
</body>
</html>
- http://localhost/board/register
- http://localhost/logout
- http://localhost/notice/register
'대덕인재개발원 > 대덕인재개발원_웹기반 애플리케이션' 카테고리의 다른 글
231212_SPRING 2 (15-2) (0) | 2023.12.12 |
---|---|
231212_SPRING 2 (15-1) (0) | 2023.12.11 |
231208_SPRING 2 (13-2) (0) | 2023.12.08 |
231208_SPRING 2 (13-1) (0) | 2023.12.08 |
231207_SPRING 2 (12-2) (1) | 2023.12.07 |