SpringMVC

Spring Web Security (4) - Oracle 연동

알아가자 2021. 9. 27. 20:26

실습

  • 스프링 레거시 프로젝트로 생성
  • java-version : 1.8
  • springframework-version : 5.2.14.RELEASE
  • springsecurity.version : 4.0.1.RELEASE
  • https://programmingbeginner.tistory.com/63 pom.xml 기본 설정 

1. pom.xml 수정(새로 추가 : jdbc, orm, tx, ojdbc6)

<!-- 추가 시작 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<!-- 오라클 디비 -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>

2. 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>
	<!-- 시큐리티 필터 등록 종료  -->
	<!-- 스프링 인코딩 필터 등록 시작 -->
	<filter>
		<filter-name>encodingFilter</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>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<!-- 스프링 인코딩 필터 등록 종료 -->

3. root-context.xml 

<!-- 시큐리티 권한설정 시작 -->
	<security:http auto-config="true" use-expressions="true">
		<security:intercept-url pattern="/" access="permitAll" />
		<security:intercept-url pattern="/home" access="permitAll" />
		<security:intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
		<security:intercept-url pattern="/dba**" access="hasRole('ADMIN') and hasRole('DBA')" />
		<!-- 접근 불가능한 곳에 접근시 처리할 페이지 지정 -->
		<security:access-denied-handler error-page="/403" />
		<!-- 사용자가 만든 로그인 페이지를 사용하려면 이부분을 수정한다. -->
		<security:form-login 
		login-page="/login" 
		username-parameter="userid" 
		password-parameter="password"
		default-target-url="/"
		authentication-failure-url="/login?error" /> <!-- 로그인 실패시 이동하 페이지 지정 -->
		<security:logout logout-success-url="/login?logout"/> <!-- 로그아웃 성공시 이동할 페이지 지정 -->
		<!-- csrf 프로텍션을 사용하겠다. -->
		<security:csrf />
	</security:http>
	<!-- 시큐리티 권한설정 종료 -->
	<!-- 시큐리티 사용자 설정 시작 -->
	<security:authentication-manager>
		<!-- 
		<security:authentication-provider>
			<security:jdbc-user-service data-source-ref="dataSource"
			users-by-username-query="select username as username, password as password, enabled from users where username=?"
			authorities-by-username-query="select username, role from user_roles where username=?"
			/>
		 -->
		<security:authentication-provider>
			<security:jdbc-user-service data-source-ref="dataSource"
			users-by-username-query="select userid as username, password , 1 from member where userid=?"
			authorities-by-username-query="select username, role from user_roles where username=?"
			/>
		</security:authentication-provider>
	</security:authentication-manager>

	<!-- 시큐리트 암호화 객체 등록  -->
	<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
	<!-- 시큐리티 사용자 설정 종료 -->

	<!-- dataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" />
		<property name="username" value="jspuser" />
		<property name="password" value="123456" />
  	</bean>
  • 시큐리티 권한을 설정한다.
  • 권한에 따라 금지된 페이지 에러는 403에러이다. 403에러가 발생할 경우 403.jsp로 이동하도록 설정
  • 로그인 실패시 login.error로 이동한다. jsp페이지는 만들지 않고 바로 login.jsp에 빨갛게 실패했다는 표시를 띄울 것이다. 

  • 시큐리티 사용자를 설정한다. (db와 연동하기 때문에 맨 밑에 dataSource객체를 생성해준다.) 생성자로 dataSource를 넣어준다.

4. table 생성 (회원관리를 위한 테이블을 작성한다.)

-- 사용자 테이블 :  나중에 회원관리할때 다른 정보도 추가로 넣을 수 있다!!!!
CREATE SEQUENCE users_idx_seq;
CREATE TABLE users(
	idx NUMBER PRIMARY KEY,
	username varchar2(100) NOT NULL,
	password varchar2(100) NOT NULL,
	enabled NUMBER DEFAULT 1
);
INSERT INTO users VALUES (users_idx_seq.nextval, 'user1', '1234', 1);
INSERT INTO users VALUES (users_idx_seq.nextval, 'admin', '1234', 1);
INSERT INTO users VALUES (users_idx_seq.nextval, 'dba', '1234', 1);
INSERT INTO users VALUES (users_idx_seq.nextval, 'root', '1234', 1);
INSERT INTO users VALUES (users_idx_seq.nextval, 'dba2', '1234', 1);
COMMIT;
SELECT * FROM users;

-- 권한 등록 테이블
CREATE SEQUENCE user_roles_idx_seq;
CREATE TABLE  user_roles(
	idx NUMBER PRIMARY KEY,
	username varchar2(100) NOT NULL,
	ROLE varchar2(30) NOT null
);
SELECT * FROM user_roles;
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'user1', 'ROLE_USER');
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'admin', 'ROLE_ADMIN');
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'dba', 'ROLE_ADMIN');
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'dba', 'ROLE_DBA');
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'root', 'ROLE_USER');
INSERT INTO user_roles VALUES (user_roles_idx_seq.nextval, 'dba2', 'ROLE_USER');

COMMIT;
SELECT * FROM user_roles;
  • 사용자 테이블

  • 권한 등록 테이블

5. Controller 작성

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		String formattedDate = dateFormat.format(date);
		model.addAttribute("serverTime", formattedDate );
		model.addAttribute("user", getPrincipal());
		return "home";
	}
	@RequestMapping(value = "/home")
	public String homepage(Model model) {
		model.addAttribute("msg","여기는 누구나 접근 가능한 페이지입니다.");
		model.addAttribute("user", getPrincipal());
		return "welcome";
	}
	/*
	@RequestMapping(value = "/Access_Denied")
	public String Access_Denied(Model model) {
		model.addAttribute("msg","등록되지 않은 사용자이거나 비밀번호가 일치하지 않습니다.");
		return "Access_Denied";
	}
	*/
	@RequestMapping(value = "/login")
	public String login(
			@RequestParam(value = "error", required = false) String error,
			@RequestParam(value = "logout", required = false) String logout,
			Model model) {
		
		if (error!=null) {
			model.addAttribute("error","아이디나 비번 없다");
		}
		if (logout!=null) {
			model.addAttribute("msg","로그아웃 성공!!!");
		}
		return "login";
	}
	
	// 접근 권한이 없는 페이지에 접근하면 보여줄 페이지
	@RequestMapping(value = "/403")
	public String page403(Model model) {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(!(authentication instanceof AnonymousAuthenticationToken)) {
			UserDetails userDetails = (UserDetails) authentication.getPrincipal();
			System.out.println(userDetails);
			model.addAttribute("username", userDetails.getUsername());
		}
		return "403";
	}
	
	/*
	@RequestMapping(value = "/logout")
	public String logout(HttpServletRequest request, HttpServletResponse response) {
		// 시큐리트를 이용하여  인증 정보를 얻어낸다. 
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(authentication!=null) { // 인증  정보가 있으면
			new SecurityContextLogoutHandler().logout(request, response, authentication); // 로그아웃을 시킨다.
		}
		return "redirect:/";
	}
	*/
	
	@RequestMapping(value = "/admin")
	public String admin(Model model) {
		model.addAttribute("msg", "관리자 전용 페이지 입니다.");
		model.addAttribute("user", getPrincipal());
		return "admin";
	}
	
	@RequestMapping(value = "/dba")
	public String dba(Model model) {
		model.addAttribute("msg", "DB관리자 전용 페이지 입니다.");
		model.addAttribute("user", getPrincipal());
		return "dba";
	}
	// 인증정보를 시큐리티에서 얻어내는 메서드
	private String getPrincipal() {
		String username = "";
		Object object = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if(object instanceof UserDetails) {
			username = ((UserDetails) object).getUsername();
		}else {
			username = object.toString();
		}
		return username;
	}
	
	// 암호화 하기 테스트
	@Autowired
	BCryptPasswordEncoder bCryptPasswordEncoder;
	
	// 평문 비번을 암호화 하기 
	@RequestMapping(value = "/getPwd")
	public String getPassword(
			@RequestParam(value = "pwd", required = false) String password,
			Model model) {
		if(password==null) password = "admin";
		String newPassword = bCryptPasswordEncoder.encode(password);
		model.addAttribute("password", password);
		model.addAttribute("newPassword", newPassword);
		return "bcrypt";
	}
	
	// 암호화된 비번을 비교하기
	@RequestMapping(value = "/checkPwd")
	public String checkPwd(
			@RequestParam(value = "pwd", required = false) String password,
			Model model) {
		if(password==null) password = "admin";
		
		String dbPassword = bCryptPasswordEncoder.encode("admin"); // 이렇게 DB에 저장되었다고 가정
		boolean isCheck1 = bCryptPasswordEncoder.matches(password, dbPassword); // 일치여부 판단하기(반드시 이놈으로 비교해야 함)
		model.addAttribute("isCheck1", isCheck1);

		String newPassword = bCryptPasswordEncoder.encode(password); 
		boolean isCheck2 = newPassword.equals(dbPassword); // 일치여부 판단하기 (않된다)
		model.addAttribute("isCheck2", isCheck2);
		
		model.addAttribute("dbPassword", dbPassword);
		model.addAttribute("newPassword", newPassword);
		
		
		return "bcrypt2";
	}

 

 

  • 일단 403, login 을 수정한다. 
	@RequestMapping(value = "/403")
	public String page403(Model model) {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(!(authentication instanceof AnonymousAuthenticationToken)) {
			UserDetails userDetails = (UserDetails) authentication.getPrincipal();
			System.out.println(userDetails);
			model.addAttribute("username", userDetails.getUsername());
		}
		return "403";
	}

-> Authentication 객체에 시큐리티를 통해 권한을 얻고 

authentication이 AnonymousAuthenticationToken의 자식 객체가 아니면 -> 로그인 되어 있는데 권한이 걸린다는 뜻

-> username을 getPrincipal()을 통해 알아낸다음. userDetails에 넣고 

-> model.addAttribute로 넘겨준다.

  • 403.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>접근 금지</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" ></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script	src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
	$(function(){
	
	});
</script>
</head>
<body>
	<h1>HTTP Status 403 -  Access is denied</h1>
	<c:choose>
		<c:when test="${empty username }">
			<h2>당신은 이 페이지에 접근할 수 있는 권한이 없습니다.</h2>
		</c:when>
		<c:otherwise>
			<h2>${username }님은 이 페이지에 접근할 수 있는 권한이 없습니다.</h2>
		</c:otherwise>
	</c:choose>
</body>
</html>
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- IE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
  • 암호화 하기 테스트를 하기 위해 root-context.xml에 BCryptPasswordEncoder 클래스를 설정해주었다.
  • 이를 controller에서 주입받는다.
  • @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;
@RequestMapping(value = "/getPwd")
	public String getPassword(
			@RequestParam(value = "pwd", required = false) String password,
			Model model) {
		if(password==null) password = "admin";
		String newPassword = bCryptPasswordEncoder.encode(password);
		model.addAttribute("password", password);
		model.addAttribute("newPassword", newPassword);
		return "bcrypt";
	}

 

// 암호화된 비번을 비교하기
	@RequestMapping(value = "/checkPwd")
	public String checkPwd(
			@RequestParam(value = "pwd", required = false) String password,
			Model model) {
		if(password==null) password = "admin";
		
		String dbPassword = bCryptPasswordEncoder.encode("admin"); // 이렇게 DB에 저장되었다고 가정
		boolean isCheck1 = bCryptPasswordEncoder.matches(password, dbPassword); // 일치여부 판단하기(반드시 이놈으로 비교해야 함)
		model.addAttribute("isCheck1", isCheck1);

		String newPassword = bCryptPasswordEncoder.encode(password); 
		boolean isCheck2 = newPassword.equals(dbPassword); // 일치여부 판단하기 (않된다)
		model.addAttribute("isCheck2", isCheck2);
		
		model.addAttribute("dbPassword", dbPassword);
		model.addAttribute("newPassword", newPassword);
		
		
		return "bcrypt2";
	}

-> home화면에 "/getPwd"와 "/checkPwd" 버튼을 만들어 줄 것이다.

 

-> 비밀번호를 암호화 시키는 과정이 getpassword 메서드이다. value ="pwd"이거는 주소 뒤에 ?pwd="어떤 값" 혹은 ?값을 넘기면 String password에 매개변수로 넣어지고, 이를 주입받은 bCryptPasswordEncode를 통해 암호화 시킨다. 이를 비교하여 볼 수 있게 "bcypt.jsp"에 넘겨준다.

 

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비번 암호화 하기</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" ></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script	src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
	$(function(){
	
	});
</script>
</head>
<body>
	비번 암호화 전 : ${password } <br />
	비번 암호화 후 : ${newPassword } <br />
	<a href="${pageContext.request.contextPath }">홈으로</a>
</body>
</html>
  • 암호화된 비밀번호를 비교하는 방법
// 암호화된 비번을 비교하기
	@RequestMapping(value = "/checkPwd")
	public String checkPwd(
			@RequestParam(value = "pwd", required = false) String password,
			Model model) {
		if(password==null) password = "admin";
		
		String dbPassword = bCryptPasswordEncoder.encode("admin"); // 이렇게 DB에 저장되었다고 가정
		boolean isCheck1 = bCryptPasswordEncoder.matches(password, dbPassword); // 일치여부 판단하기(반드시 이놈으로 비교해야 함)
		model.addAttribute("isCheck1", isCheck1);

		String newPassword = bCryptPasswordEncoder.encode(password); 
		boolean isCheck2 = newPassword.equals(dbPassword); // 일치여부 판단하기 (않된다)
		model.addAttribute("isCheck2", isCheck2);
		
		model.addAttribute("dbPassword", dbPassword);
		model.addAttribute("newPassword", newPassword);
		
		
		return "bcrypt2";
	}

-> 위와 비슷하게 홈 화면에 "/checkPwd"로 이동되는 버튼을 생성 후 누르면 실행될 메서드이다.

-> 마찬가지로 pwd를 매개 변수로 받아 password에 넣고

-> DB에 있는 비밀번호가 "admin"이라고 했을 때 

-> bCyptPasswordEncoder.matches(password, dbPassword); 하면 일치여부를 판단할 수 있다.

 

-> equals를 사용했을 시에는 일치하지 않는다고 나오게 된다. bCyptPasswordEncoder.matches를 사용하자.

  • bcypt2.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>비번 비교하기</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" ></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script	src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
	$(function(){
	
	});
</script>
</head>
<body>
	${newPassword } <br />
	${dbPassword } <br />
	${isCheck1 ? "일치":"불일치" } <br />
	${isCheck2 ? "일치":"불일치" } <br />
	<a href="${pageContext.request.contextPath }">홈으로</a>
</body>
</html>

 

  • home.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<html>
<head>
<meta charset="UTF-8"/>
<title>Home</title>
</head>
<body>
	<h1>Hello world!</h1>

	<P>The time on the server is ${serverTime}.</P>

	<hr />
	현재 사용자 : ${user }
	<br />
	<hr />
	<a href="admin">관리자 페이지 가기</a>
	<a href="dba">DB관리자 페이지 가기</a>
	<a href="home">일반페이지 가기</a>
	<c:if test='${user!="anonymousUser" }'>
		<a href="${pageContext.request.contextPath }/logout?_csrf=${_csrf.token}">로그아웃</a>
	</c:if>
	<c:if test='${user=="anonymousUser" }'>
		<a href="${pageContext.request.contextPath }/login">로그인</a>
	</c:if>
	<hr />
		<c:if test="${pageContext.request.userPrincipal.name != null}">
			<c:url value="/logout" var="logoutUrl" />
			<form action="${logoutUrl}" method="post" id="logoutForm">
				<%-- 시큐리티에 있는 로그아웃을 사용하려면 아래의 내용도 넘겨줘야 한다. --%>
				<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
				<input type="submit" value="로그아웃">
			</form>
		</c:if>
	<hr />
	<a href="${pageContext.request.contextPath }/getPwd">비밀번호 암호화 확인하기</a>
	<a href="${pageContext.request.contextPath }/checkPwd">비밀번호 일치비교 확인하기</a>
</body>
</html>
  • login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login page</title>
<link rel="stylesheet"
	href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script
	src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>

<link rel="stylesheet" type="text/css"
	href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css" />
	
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath }/resources/css/app.css" />
</head>

<body>
	<div id="mainWrapper">
		<div class="login-container">
			<div class="login-card">
				<div class="login-form">
					<form action="<c:url value="/login"/>" method="post" class="form-horizontal">
					
						<c:if test="${not empty error}">
							<div style="color: red;">${error }</div>
						</c:if>
						<c:if test="${not empty msg}">
							<div style="color: blue;">${msg }</div>
						</c:if>
					
						<div class="input-group input-sm">
							<label class="input-group-addon" for="username"><i
								class="fa fa-user"></i></label> <input type="text" class="form-control"
								id="username" name="userid" placeholder="Enter Username" required>
						</div>
						<div class="input-group input-sm">
							<label class="input-group-addon" for="password"><i
								class="fa fa-lock"></i></label> <input type="password"
								class="form-control" id="password" name="password"
								placeholder="Enter Password" required>
						</div>
						<!-- 시큐리트에서 사용자가 지정한 폼을 사용하려면 반드시 아래의 코드를 첨부해줘야 한다.-->
						<input type="hidden" name="${_csrf.parameterName}"
							value="${_csrf.token}" />

						<div class="form-actions">
							<input type="submit"
								class="btn btn-block btn-primary btn-default" value="Log in">
						</div>
					</form>
				</div>
			</div>
		</div>
	</div>

</body>
</html>

 

내용이 조금 많아져서 정리를 나중에 한 번 해봐야 할 것 같다...