본문 바로가기
Spring/Spring 기초

Security 폼 기반 인증 기능 사용(로그인 처리)

by 미눅스[멘토] 2023. 8. 17.
728x90

폼기반 인증 기능 사용

security-context.xml에

 

      <!-- 폼 기반 인증 기능 사용 -->
      <security:form-login/>

 

작성

 

 

 

사용자가 정의한 로그인

security-context.xml에

	  <!-- 사용자가 정의한 로그인(인증 : authentication) 페이지의 URI를 지정 -->
<!--       <security:form-login login-page="/member/loginMember" /> -->
	  <!-- 인증 성공 시 처리해줄 클래스의 인스턴스 명 작성 -->

 

 


 

 

 

인증 성공 시 처리해줄 클래스의 인스턴스 명 작성 하고

	  <!-- 인증 성공 시 처리해줄 클래스의 인스턴스 명 작성 -->
      <security:form-login login-page="/member/loginMember"
      	authentication-success-handler-ref="customLoginSuccess" />

 

login-page에 작성한 경로에 jsp생성

 

코드작성

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<!-- 402호 경민 -->
<div class="login-box" style="margin:auto; padding-top: 150px;">
	<div class="login-logo">
		<a href="/member/loginMember"><b>로그인</b></a>
	</div>

	<div class="card">
		<div class="card-body login-card-body">
			<p class="login-box-msg">Sign in to start your session</p>
			<!-- 시큐리티 로그인 폼 규칙
			1. action="/login"
			2. method="post"
			3. 아이디 : name = "username"
			4. 비밀번호 : name="password"
			5. csrf : Cross Site Request Forgery(웹 어플리케이션 취약점) 공격 그리고 방어
			 -->
			<form action="/login" method="post">
				<div class="input-group mb-3">
					<input type="text" name="username"
						 class="form-control" placeholder="아이디" />
					<div class="input-group-append">
						<div class="input-group-text">
							<span class="fas fa-envelope"></span>
						</div>
					</div>
				</div>
				<div class="input-group mb-3">
					<input type="password" name="password"
						 class="form-control" placeholder="비밀번호" />
					<div class="input-group-append">
						<div class="input-group-text">
							<span class="fas fa-lock"></span>
						</div>
					</div>
				</div>
				<div class="row">
					<div class="col-8">
						<div class="icheck-primary">
							<input type="checkbox" id="remember"> <label
								for="remember"> Remember Me </label>
						</div>
					</div>

					<div class="col-4">
						<button type="submit" class="btn btn-primary btn-block">Sign
							In</button>
					</div>
				</div>
				<!-- 폼안에 이거 추가해줘야함 -->
				<sec:csrfInput/>
			</form>
		</div>
	</div>
</div>

 

 

 

security-context.xml에

bean객체를 생성한다.

   <!-- 로그인 성공 처리
   	로그인 성공 후 이력 로그를 기록(DB, 파일)과 같은 작업을 하고자 할 떄 사용
    -->
    <bean id="customLoginSuccess" 
    	class="kr.or.ddit.cecurity.CustomLoginSuccessHandler">
    </bean>

bean 객체에 

class에 지정한 패키지 및 클래스 작성

 

 

package kr.or.ddit.cecurity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.security.authentication.jaas.AuthorityGranter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import lombok.extern.slf4j.Slf4j;

/*
 /notice/register -> loginMember -> 로그인 시도 -> 성공 (CustomLoginSuccess)
  -> 사용자 작업 수행 -> /notice/register로 다이렉트 해줌
 */
@Slf4j
public class CustomLoginSuccessHandler extends
	SavedRequestAwareAuthenticationSuccessHandler{
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication auth)
			throws ServletException, IOException {
		log.warn("onAuthenticationSuccess!!");
		
		//auth.getPrincipal() : 사용자 정보를 가져옴
		// 시큐리티에서 사용자 정보는 User 클래스의 객체로 저장됨(CustomUser.java 참고)
		User customUser = (User)auth.getPrincipal();
		
		log.info("username : " + customUser.getUsername());
		
		//팁! 로그인 성공 시 나오는 페이지 url설정 - 관리자, 사용자, 업체, 일반회원에 따라 다르게 처리
		List<String> roleNames = new ArrayList<String>();
		//auth.getAuthorities() : 사용자(1)의 권한(N)정보들
		auth.getAuthorities().forEach(authority->{
			roleNames.add(authority.getAuthority());
		});
		
		log.info("ROLE NAMES : " + roleNames);
		
		//일반회원(ROLE_MEMBER)
//		if(roleNames.contains("ROLE_MEMBER")) {
//			response.sendRedirect("/member/main");
//		}
		
		//관리자(ROLE_ADMIN)
//		if(roleNames.contains("ROLE_ADMIN")) {
//			response.sendRedirect("/admin/main");
//		}
		
		//부모(super)에게 반납
		super.onAuthenticationSuccess(request, response, auth);
	}
}

 

 

 

 

 

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">
<!-- xmlns:security는 스프링 시큐리티가 제공하는 XML 네임스페이스를 활성화 -->
	<!-- 인가(authorization) 불허
		bean : 객체 / class="우리가 만든 클래스" / id : 우리가 만든 클래스를 인스턴스화 하여 만든 객체명
	 -->
	<bean id="customAccessDenied"
		class="kr.or.ddit.cecurity.CustomAccessDeniedHandler">
	</bean>
   
   <!-- 로그인 성공 처리
   	로그인 성공 후 이력 로그를 기록(DB, 파일)과 같은 작업을 하고자 할 떄 사용
    -->
    <bean id="customLoginSuccess" 
    	class="kr.or.ddit.cecurity.CustomLoginSuccessHandler">
    </bean>
   
   <security:http>
      <!-- 접근 제한 설정: 시큐리티 설정을 통해서 특정 URI에 대한 접근을 제한할 수 있음
         - Role: 권한 / hasRole: 권한 소유 유무
         - permitAll: 누구나 접근 가능
      -->
      <security:intercept-url pattern="/freeboard/list" access="permitAll" />
      <security:intercept-url pattern="/freeboard/register" access="hasRole('ROLE_MEMBER')" />
      <security:intercept-url pattern="/notice/list" access="permitAll" />
      <security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
      <!-- 폼 기반 인증 기능 사용 -->
      <security:form-login/>
	  <!-- 사용자가 정의한 로그인(인증 : authentication) 페이지의 URI를 지정 -->
<!--       <security:form-login login-page="/member/loginMember" /> -->
	  <!-- 인증 성공 시 처리해줄 클래스의 인스턴스 명 작성 -->
      <security:form-login login-page="/member/loginMember"
      	authentication-success-handler-ref="customLoginSuccess" />
      
	  <!--<sec:csrfInput/> 생략가능-->
<!--       <security:csrf disabled="true"/> -->
      
      <!-- 1. 접근 거부 처리(사용자 정의)
      	접근 거부가 발생한 상황에 단순 메시지 처리 이상의 다양한 처리를 하고 싶다면
      	AccessDeniedHandler를 직접 구현햐야 함
       -->
<!--       <security:access-denied-handler ref="customAccessDenied"/> -->
      <!-- 
      1. 접근 거부 처리(시큐리티  제공)
      1) 선제조건 : 계정 / 비밀번호가 맞아야 함 => 로그인 가능
      2) 들어가려는 URL에 대한 권한이 없어야 함
      	/notice/register 요청에 member / java로 로그인한 경우[ROLE_MEMBER]
       -->
<!--       <security:access-denied-handler error-page="/security/accessError"/> -->
      
      
   </security:http>
   
   <!--
      authentication: 인증(로그인)
      authorization: 인가(로그인 후의 권한)
      authorities : 권한들
             로그인 처리.
             메모리상에 아이디와 패스워드를 지정하고 로그인을 처리함
             스프링 시큐리티(5.0.7.RELEASE버전) 5버전부터는 패스워드 암호화 처리기를 반드시 이용해야 함
             암호화 처리기를 사용하지 않으려면 noop 문자열을  비밀번호 앞에 사용함
   -->
   <security:authentication-manager>
   		<security:authentication-provider>
   			<security:user-service>
   				<security:user name="member" password="{noop}java"
   					authorities="ROLE_MEMBER"/>
   				<security:user name="admin" password="{noop}java"
   					authorities="ROLE_ADMIN" />
   			</security:user-service>
   		</security:authentication-provider>
   </security:authentication-manager>
</beans>