[로그인처리] Spring security 1
2021. 10. 4. 16:20
< 보안 관련 프로젝트 생성 >
1. 프로젝트 생성
2. 한글 처리
3. 보안 관련 라이브러리 추가
4. 스프링 설정 파일 분리
5. 보안 관련 설정 파일 만들기
pom.xml
4개의 라이브러리 설정 - 버전주의
- 스프링 시큐리티를 사용하기 위해서 다운로드 해야한다.(4가지)
- 스프링 시큐리티는 스프링 프레임워크(5.0.7)보다 낮은 버전(5.0.6)을 사용해야 한다.
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.9.0</org.aspectj-version>
<org.slf4j-version>1.7.25</org.slf4j-version>
<org.security-version>5.0.6.RELEASE</org.security-version>
</properties>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${org.security-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${org.security-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${org.security-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${org.security-version}</version>
</dependency>
web.xml
- 한글 처리 밑에 시큐리티 객체 생성
- contextConfigLocation에 해당 xml 집어넣기
- /WEB-INF/spring/security-context.xml 추가하기
<!-- 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>
<!-- Spring Security Filter -->
<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>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
⇒ 12개의 필터 객체를 생성함.
security-context.xml
- root-context.xml 복사하고 Namespaces에서 ✔️security
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<http>
<form-login />
</http>
<!-- provider -->
<authentication-manager>
</authentication-manager>
</beans:beans>
*책에는 이렇게 되어있다. (security:)
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
<!-- provider -->
<security:authentication-manager>
</security:authentication-manager>
</beans:beans>
- 지금까지 우리가 했던 프로그래밍은 컨트롤러에서 login.jsp로 처리했는데, 스프링 시큐리티가 로그인을 처리해주고 있다. (왜? 내가 컨트롤러에서 처리하고 있지 않으므로)
- 내가 처리해주지 않는 이상 누군가가 낚아채고 있는게 핵심이다.
어디에서 처리하는가?
1)
Maven Dependecies → spring-security-web-5.0.6.RELEASE.jar → org.springframework.security.web.authentication.ui → DefaultLoginPageGenerationFilter.class
2)
Maven Dependecies → spring-security-web-5.0.6.RELEASE.jar →
org.springframework.security.web.server.ui → LoginPageGeneratingWebFilter.class
if (formLoginEnabled) {
sb.append("<h3>Login with Username and Password</h3>");
sb.append("<form name='f' action='").append(request.getContextPath())
.append(authenticationUrl).append("' method='POST'>\n");
sb.append("<table>\n");
sb.append(" <tr><td>User:</td><td><input type='text' name='");
sb.append(usernameParameter).append("' value='").append("'></td></tr>\n");
sb.append(" <tr><td>Password:</td><td><input type='password' name='")
.append(passwordParameter).append("'/></td></tr>\n");
if (rememberMeParameter != null) {
sb.append(" <tr><td><input type='checkbox' name='")
.append(rememberMeParameter)
.append("'/></td><td>Remember me on this computer.</td></tr>\n");
}
sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
renderHiddenInputs(sb, request);
sb.append("</table>\n");
sb.append("</form>");
}
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.server.ui;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.web.server.csrf.CsrfToken;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
/**
* Generates a default log in page used for authenticating users.
*
* @author Rob Winch
* @since 5.0
*/
public class LoginPageGeneratingWebFilter implements WebFilter {
private ServerWebExchangeMatcher matcher = ServerWebExchangeMatchers
.pathMatchers(HttpMethod.GET, "/login");
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return this.matcher.matches(exchange)
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
.flatMap(matchResult -> render(exchange));
}
private Mono<Void> render(ServerWebExchange exchange) {
ServerHttpResponse result = exchange.getResponse();
result.setStatusCode(HttpStatus.OK);
result.getHeaders().setContentType(MediaType.TEXT_HTML);
return result.writeWith(createBuffer(exchange));
}
private Mono<DataBuffer> createBuffer(ServerWebExchange exchange) {
MultiValueMap<String, String> queryParams = exchange.getRequest()
.getQueryParams();
Mono<CsrfToken> token = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
return token
.map(LoginPageGeneratingWebFilter::csrfToken)
.defaultIfEmpty("")
.map(csrfTokenHtmlInput -> {
boolean isError = queryParams.containsKey("error");
boolean isLogoutSuccess = queryParams.containsKey("logout");
byte[] bytes = createPage(isError, isLogoutSuccess, csrfTokenHtmlInput);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
return bufferFactory.wrap(bytes);
});
}
private static byte[] createPage(boolean isError, boolean isLogoutSuccess, String csrfTokenHtmlInput) {
String page = "<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n"
+ " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n"
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ createError(isError)
+ createLogoutSuccess(isLogoutSuccess)
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ csrfTokenHtmlInput
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ " </div>\n"
+ " </body>\n"
+ "</html>";
return page.getBytes(Charset.defaultCharset());
}
private static String csrfToken(CsrfToken token) {
return " <input type=\"hidden\" name=\"" + token.getParameterName() + "\" value=\"" + token.getToken() + "\">\n";
}
private static String createError(boolean isError) {
return isError ? "<div class=\"alert alert-danger\" role=\"alert\">Invalid credentials</div>" : "";
}
private static String createLogoutSuccess(boolean isLogoutSuccess) {
return isLogoutSuccess ? "<div class=\"alert alert-success\" role=\"alert\">You have been signed out</div>" : "";
}
}
'BackEnd > Spring Security' 카테고리의 다른 글
[Spring security] 에러페이지 추가 (0) | 2021.10.07 |
---|---|
[로그인처리] Spring securiy 4 (0) | 2021.10.05 |
[로그인처리] Spring security 3 (0) | 2021.10.05 |
[로그인처리] Spring security 2 (0) | 2021.10.04 |
[로그인처리] Spring Web Security (0) | 2021.10.04 |