KDT/WEB

240322 WEB - 보안 3

001cloudid 2024. 3. 22. 17:50
728x90

보안

로그인

SampleController.java

(...생략...)
	//sample/customLogin
	@GetMapping("/customLogin")
	public void doCustomLogin(String error, String logout, Model model) {
		System.out.println("doCustomLogin()");
		
		System.out.println("error : " + error);
		System.out.println("logout : " + logout);
		
		//참조형이 비어있는 경우 => null
		if(error != null) {
			model.addAttribute("error","Login Error");
		}
		if(logout != null) {
			model.addAttribute("logout","Logout");
		}
		
	}

 

customLogin.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>sample/customLogin.jsp</title>
</head>
<body>
<h1>sample/customLogin.jsp</h1>
<h1>error : ${error}</h1>
<h1>logout : ${logout}</h1>

<form action="/login" method="post">
아이디  : <input type="text" name="username" value="admin"><br>
비밀번호 : <input type="password" name="password"><br>
<input type="submit" value="로그인">
<!-- csrf : 사이트 간 요청 위조 공격 -->
<!-- _csrf.parameterName _csrf.token token 임의의값 -->
<!-- csrf 토큰 : 사용자가 임의로 변하는 특정한 토큰값을 서버에서 체크하는 방식 -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token }">
</form>
</body>
</html>

 

페이지에서 우클릭 소스보기 했을때 csrf 이름과 토큰값을 볼 수 있음

 

토큰값을 비활성화하려면

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/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">


<!-- 객체 생성 -->
<bean id="customAccessDenied" class="com.itwillbs.security.CustomAccessDeniedHandler"></bean>

<!-- 웹 주소 연결 -->
<security:http>
<!-- 특정한 URL에 접근할 때 인터셉터를 이용해서 접근을 제한하는 설정. pattern과 access 속성을 지정 -->
	<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:form-login login-page="/sample/customLogin"/>
	
<!-- 	HTTP 상태 403 - 금지됨 => 페이지 연결 -->
<!-- 	<security:access-denied-handler error-page="가상주소"/> -->
<!-- 	<security:access-denied-handler error-page="/sample/accessError"/> -->
	<security:access-denied-handler ref="customAccessDenied" />
	
<!-- 	csrf 토큰 : 서버 세션에 저장, 브라우저에 전송 된 csrf 토큰 검사하는 방식 
		csrf 토큰 생성을 비활성화(권장하지 않음), 쿠키를 이용해서 처리
-->
	<security:csrf disabled="true"/>
	
</security:http>

<!--
	 인증 관련 내용 
	 security:authentication-manager 인증 매니저 
	 <= provider manager 
	 <= 이용해서 authentication-provider : 인증 작업 
	 <= UserdetailService : 인증된 정보 권한에 대한 정보를 같이 전달, 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환	
-->
<security:authentication-manager>

<security:authentication-provider>
	<security:user-service>
<!-- 	There is no PasswordEncoder mapped for the id "null" -->
<!-- 	noop : PasswordEncoder 없이 사용 -->
	<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER"/>
	<security:user name="admin" password="{noop}1234" authorities="ROLE_MEMBER, ROLE_ADMIN"/>
	</security:user-service>
	
</security:authentication-provider>
</security:authentication-manager>


</beans>

 

지금은 사용할 것이기 때문에 주석처리

<?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">


<!-- 객체 생성 -->
<bean id="customAccessDenied" class="com.itwillbs.security.CustomAccessDeniedHandler"></bean>

<!-- 웹 주소 연결 -->
<security:http>
<!-- 특정한 URL에 접근할 때 인터셉터를 이용해서 접근을 제한하는 설정. pattern과 access 속성을 지정 -->
	<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:form-login login-page="/sample/customLogin"/>
	
<!-- 	HTTP 상태 403 - 금지됨 => 페이지 연결 -->
<!-- 	<security:access-denied-handler error-page="가상주소"/> -->
<!-- 	<security:access-denied-handler error-page="/sample/accessError"/> -->
	<security:access-denied-handler ref="customAccessDenied" />
	
<!-- 	csrf 토큰 : 서버 세션에 저장, 브라우저에 전송 된 csrf 토큰 검사하는 방식 
		csrf 토큰 생성을 비활성화(권장하지 않음), 쿠키를 이용해서 처리
-->
<!-- 	<security:csrf disabled="true"/> -->
	
</security:http>

<!--
	 인증 관련 내용 
	 security:authentication-manager 인증 매니저 
	 <= provider manager 
	 <= 이용해서 authentication-provider : 인증 작업 
	 <= UserdetailService : 인증된 정보 권한에 대한 정보를 같이 전달, 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환	
-->
<security:authentication-manager>

<security:authentication-provider>
	<security:user-service>
<!-- 	There is no PasswordEncoder mapped for the id "null" -->
<!-- 	noop : PasswordEncoder 없이 사용 -->
	<security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER"/>
	<security:user name="admin" password="{noop}1234" authorities="ROLE_MEMBER, ROLE_ADMIN"/>
	</security:user-service>
	
</security:authentication-provider>
</security:authentication-manager>


</beans>

 

CutstomLoginSuccessHandler.java

package com.itwillbs.security;

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.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler{

	//	로그인 성공 후에 특정한 동작을 하도록 제어
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		System.out.println("Login Success");
		
		List<String> roleNames = new ArrayList<String>();
		
		authentication.getAuthorities().forEach(authority->{
			roleNames.add(authority.getAuthority());
		});
		
		if(roleNames.contains("ROLE_ADMIN")) {
			response.sendRedirect(request.getContextPath()+"/sample/admin");
			return;
		}
		
		if(roleNames.contains("ROLE_MEMBER")) {
			response.sendRedirect(request.getContextPath()+"/sample/member");
			return;
		}
		response.sendRedirect(request.getContextPath()+"/");
	}


	
}

 

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/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">


<!-- authentication-manager 인증매니저 
     <= provider manager 
     <= 이용 authentication-provider : 인증작업
     <= UserdetailService : 인증된 정보에 권한에 대한 정보를 같이 전달 
                          : 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환-->

<bean id="customAccessDenied" 
class="com.itwillbs.security.CustomAccessDeniedHandler"></bean>

<bean id="customLoginSuccess"
class="com.itwillbs.security.CustomLoginSuccessHandler"></bean>

<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')"/>

<!-- 	http://localhost:8080/secu/login -->

<!-- 	<security:form-login/> -->
		<security:form-login login-page="/sample/customLogin"
		authentication-success-handler-ref="customLoginSuccess"/>
	
<!-- 	HTTP 상태 403 – 금지됨 => 페이지 연결-->
<!-- 	<security:access-denied-handler error-page="/sample/accessError"/> -->
<security:access-denied-handler ref="customAccessDenied"/>

<!-- 		csrf 토큰  : 서버에 세션에 저장, 브라우저에 전송 된 csrf 토큰 검사하는 방식 
			csrf 토큰 생성을 비활성화, 쿠키를 이용해서 처리-->
<!-- 			<security:csrf disabled="true"/> -->
	
</security:http>

<security:authentication-manager>

<security:authentication-provider>

	<security:user-service>
<!-- 	There is no PasswordEncoder mapped for the id "null" 
		noop : PasswordEncoder 없이 사용-->
		<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>

 

로그아웃

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/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">


<!-- authentication-manager 인증매니저 
     <= provider manager 
     <= 이용 authentication-provider : 인증작업
     <= UserdetailService : 인증된 정보에 권한에 대한 정보를 같이 전달 
                          : 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환-->

<bean id="customAccessDenied" 
class="com.itwillbs.security.CustomAccessDeniedHandler"></bean>

<bean id="customLoginSuccess"
class="com.itwillbs.security.CustomLoginSuccessHandler"></bean>

<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')"/>

<!-- 	http://localhost:8080/secu/login -->

<!-- 	<security:form-login/> -->
		<security:form-login login-page="/sample/customLogin"
		authentication-success-handler-ref="customLoginSuccess"/>
		
		<security:logout logout-url="/sample/logout" invalidate-session="true"/>
	
<!-- 	HTTP 상태 403 – 금지됨 => 페이지 연결-->
<!-- 	<security:access-denied-handler error-page="/sample/accessError"/> -->
<security:access-denied-handler ref="customAccessDenied"/>

<!-- 		csrf 토큰  : 서버에 세션에 저장, 브라우저에 전송 된 csrf 토큰 검사하는 방식 
			csrf 토큰 생성을 비활성화, 쿠키를 이용해서 처리-->
<!-- 			<security:csrf disabled="true"/> -->
	
</security:http>

<security:authentication-manager>

<security:authentication-provider>

	<security:user-service>
<!-- 	There is no PasswordEncoder mapped for the id "null" 
		noop : PasswordEncoder 없이 사용-->
		<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>

 

SampleController.java

	@GetMapping("/customLogout")
	public void customLogoutGet() {
		System.out.println("customLogoutGet()");
		// 화면  /sample/customLogout
	}

 

customLogout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>sample/customLogout.jsp</title>
</head>
<body>
<h1>sample/customLogout.jsp</h1>

<form action="${pageContext.request.contextPath}/customLogout" method="post">
<input type="submit" value="로그아웃">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token }">
</form>

</body>
</html>

 

admin.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>sample/admin.jsp</title>
</head>
<body>
<h1>sample/admin.jsp</h1>
<p>관리자만 접근 가능</p>
<a href="${pageContext.request.contextPath}/sample/customLogout">로그아웃</a>
</body>
</html>

 

member.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>sample/member.jsp</title>
</head>
<body>
<h1>sample/member.jsp</h1>
<p>로그인한 사용자만 접근 가능</p>
<a href="${pageContext.request.contextPath}/sample/customLogout">로그아웃</a>
</body>
</html>

 

SampleController.java

	@PostMapping("/customLogout")
	public void customLogoutPost() {
		System.out.println("customLogoutPost()");
	}

 

 

728x90

'KDT > WEB' 카테고리의 다른 글

240326 WEB - 보안 5  (0) 2024.03.26
240325 WEB - 보안 4  (0) 2024.03.25
240319 WEB - 보안 2  (0) 2024.03.19
240318 WEB - 보안 1  (0) 2024.03.18
240314 WEB - 정규표현식  (0) 2024.03.14