티스토리 뷰
Spring Security : Web MVC + Security - Custom Login Form 만들기
Korean Eagle 2020. 5. 16. 23:291. 이 포스트는 Spring : Web MVC + Security 시리즈의 연속이다.
2. 이 포스트에서는 아래 빨간 박스에 있는 로그인 화면에 대한 UI를 사용자가 작성하도록 하는 것이다.
3. 작업을 나열하면
3-1 Security 설정에서 사용자 로그인를 참조하도록 설정하고
3-1-1 configure(AuthenticationManagerBuilder)는 지난 포스트에서 사용자 로그인 방식을 설정하는데 사용했다.
3-1-1-1 즉, in Memory, Database, LDAP 같은 기술로 부터 로그인을 사용하도록 지정할 수 있다.
3-1-2 configure(HttpSecurity)는 프로그램 웹경로와 로그인, 로그아웃에 대한 보안을 설정하는데 사용된다.
3-1-2-1 따라서 사용자 로그인 화면을 스프링 보안과 연결하기 위해서는 이 메소드를 사용해야 한다.
3-2 컨트롤러에서 로그인 화면에 관한 부분을 작성한다.
3-3 View 레이어의 사용자 로그인 화면을 작성한다.
4. SecurityConfig 설정하기
4-1 configure(HttpSecurity) 를 수정하여 URL에 대한 접근 제어와 Login Form에 대한 설정을 한다.
4-2 HttpSecurity는 Web기반 보안설정을 담당하는 클래스로 아래 코드를 설명하면
4-2-1 http.authorizeRequests().anyRequest().authenticated()
4-2-1-1 authorizeRequests()는 HttpServletRequest로 들어오는 요청을 필터링하여 접근을 제어한다.
4-2-1-2 anyRequest()는 들어오는 모든 요청을 의미하는 것이고
4-2-1-3 authenticated()은 위의 모든 request 요청에 대해 로그인 인증이 필수라는 것이다.
4-2-2 formLogin().loginPage().loginProcessingUrl().permitAll()
4-2-2-1 formLogin()은 로그인 설정을 할 객체를 반환한다.
4-2-2-2 loginPage("/showLoginPage")는 Controller에서 /showLoginPage라는 경로로 들어오는 request를
4-2-2-2-1 로그인 페이지 화면으로 연결하는 경로를 설정한다.
4-2-2-3 loginProcessingUrl("authenticateUser") - 사용자가 로그인 페이지에서 인증을 요청하는 url을 명시한다.
4-2-2-4 permitAll() 이런 login 처리에 사용되는 페이지에 모든 request가 다 허용된다는 의미다.
package pe.pilseong.springsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserBuilder users = User.withDefaultPasswordEncoder();
auth.inMemoryAuthentication()
.withUser(users.username("pilseong").password("pilseong").roles("EMPLOYEE"))
.withUser(users.username("suel").password("suel").roles("MANAGER"))
.withUser(users.username("noel").password("noel").roles("ADMIN"));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/showLoginPage")
.loginProcessingUrl("/authenticateUser")
.permitAll();
}
}
5. SecurityConfig에 설정된 loginPage 요청 url /showLoginPage를 처리할 Controller를 작성한다.
5-1 아주 심플하게 단순히 /showLoginPage라는 요청에 plain-login.jsp를 보여주는 메소드이다.
5-2 SecurityConfig이 모든 페이지 접근에 인증이 필요하도록 설정되었으므로
5-2-1 실제 존재하는 페이지라면 무조건 /showLoginPage라는 경로로 전환되어 아래 메소드가 실행된다.
package pe.pilseong.springsecurity.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/showLoginPage")
public String showLoginPage() {
return "plain-login";
}
}
6. login로 사용될 plain-login.jsp 페이지를 작성한다.
6-1 상하단의 링크는 bootstrap설정이므로 신경 쓸 부분이 없고 중간 부분만 보면 된다.
6-2 중요한 부분은 form:form을 사용한 것인데 이것을 사용하지 않으면 제대로 처리되지 않는다.
6-2-1 form:form은 form 전송시에 추가로 보안 정보를 표함하는 토큰정보를 보내기 때문이다.
6-2-2 즉 그냥 form을 사용하면 보안 때문에 넘어가지 않는다는 메시지를 토해낸다.
6-2-3 따라서 form taglib를 사용하여 form:form을 사용한다.
6-3 다른 중요한 부분은 사용자 이름과 비밀번호를 받는 name의 기본값이 지정되어 있어 그대로 써야 한다.
6-3-1 input element에 name 속성이 'username'
6-3-2 password를 받는 input element에 name이 'password'라고 지정되어야 한다.
6-4 submit 버튼을 눌렀을 때 form 설정은 반드시 POST로 전달해야 한다.
6-5 요청하는 경로는 Security Config에 설정된 loginProcessingUrl과 동일해야 한다. 이 경우는 authenticateUser
6-6 절대 경로를 사용하고 싶은 경우
6-6-1 ${pageContext.request.contextPath} 를 사용하는 것을 언급해 둔다. context root 값을 돌려준다.
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous">
<title>Spring Security Custom Login Form</title>
</head>
<body>
<div class="container">
<div class="card" style="width: 350px; margin-left: auto; margin-right: auto; border: none;">
<h1 class="display-4">Please Login</h1>
<form:form action="${pageContext.request.contextPath}/authenticateUser" method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control">
</div>
<input type="submit" value="Login" class="btn btn-primary">
</form:form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
</body>
</html>
7. 위의 jsp페이로 표출될 유저 화면
8. 잘못된 로그인 정보로 시도 시 에러 메시지 표출하기
8-1 기능은 문제가 없지만 잘못된 정보로 로그인 할 때 아무런 반응이 없다.
8-2 잘못된 정보가 입력될 경우 스프링은 다시 로그인 페이지를 보여 주게 되고
8-3 로그인 url에 ?error 라는 parameter가 붙는다.
8-3-0 http://localhost:8080/springsecurity/showLoginPage?error url이 이렇게 나타난다.
8-3-1 아래처럼 수정하여 error parameter가 존재하는지 확인하고 있으면 error 메시지를 표출한다.
8-3-1-1 여기에서는 c taglib를 사용하였고 첫 줄에 include 코드가 추가 되었다.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous">
<title>Spring Security Custom Login Form</title>
</head>
<body>
<div class="container">
<div class="card" style="width: 350px; margin-left: auto; margin-right: auto; border: none;">
<h1 class="display-4">Please Login</h1>
<form:form action="${pageContext.request.contextPath}/authenticateUser" method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control">
<c:if test="${ param.error != null }">
<small id="passwordHelpBlock" class="form-text text-warning">
Sorry! You entered invalid username/password.
</small>
</c:if>
</div>
<input type="submit" value="Login" class="btn btn-primary">
</form:form>
</div>
</div>
8-4. 결과 화면
'Spring > Spring Security' 카테고리의 다른 글
Spring Security : Web MVC + Security - Landing Page 사용하기 (0) | 2020.05.17 |
---|---|
Spring Security : Web MVC + Security - Security JSP Tag Library 사용하기 (0) | 2020.05.17 |
Spring Security : Web MVC + Security - CSRF token 다루기 (0) | 2020.05.17 |
Spring Security : Web MVC + Security - Logout 기능 구현 (0) | 2020.05.17 |
Spring Security : Web MVC + Security with Java Config 설정하기 (0) | 2020.05.16 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- Angular
- Spring Security
- login
- one-to-many
- 스프링부트
- Many-To-Many
- Rest
- hibernate
- mapping
- Security
- form
- XML
- 로그인
- crud
- Spring
- one-to-one
- 설정하기
- 외부파일
- Validation
- spring boot
- WebMvc
- 하이버네이트
- 설정
- 자바
- 매핑
- 상속
- MYSQL
- RestTemplate
- 스프링
- jsp