본문 바로가기
Back-end

시큐리티 커스텀 로그인 폼

by 신재권 2021. 9. 3.

시큐리티 커스텀 로그인 폼 사용하기

기본으로 제공되는 로그인 폼의 디자인도 부트스트랩이 적용되어 있어 나쁘지 않다.

하지만 자체 디자인이 필요할 경우 수정할 수가 없다.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri=""http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>loginForm.jsp</title>
</head>
<body>
	<form action="<c:url value="j_spring_security_check"/>" method="post">
		ID : <input type="text" name="j_username"> <br>
		PW : <input type="text" name="j_password"> <br>
		<input type="submit" value="LOGIN"><br>  
	</form>
</body>
</html>

로그인 폼을 만들었다.

jstl을 사용하기 위해 태그 라이브러리를 추가한다.


package com.study.springboot.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/css/**", "/js/**", "/img/**").permitAll()
                .antMatchers("/guest/**").permitAll()
                .antMatchers("/member/**").hasAnyRole("USER", "ADMIN")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated();
 
        http.formLogin()
                .loginPage("/loginForm")             // default : /login
                .loginProcessingUrl("/j_spring_security_check")
                .failureUrl("/loginError")             // default : /login?error
                //.defaultSuccessUrl("/")
                .usernameParameter("j_username")    // default : j_username
                .passwordParameter("j_password")     // default : j_password
                .permitAll();
 
        http.logout()
                .logoutUrl("/logout") // default
                .logoutSuccessUrl("/")
                .permitAll();
        
        // 개발중에는 꺼 놓는다.
        http.csrf().disable();
    }
 
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user").password(passwordEncoder().encode("1234")).roles("USER")
            .and()
            .withUser("admin").password(passwordEncoder().encode("1234")).roles("ADMIN");
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
    }
}

로그인 폼의 url을 지정하고 로그인이 실패할 때 호출될 url도 지정한다.

loginProcessingUrl은 스프링의 시큐리티 인증 url이다.

로그인 폼 jsp에서 지정한 변수명으로 파라미터명을 지정한다.

로그아웃의 경우에도 url을 지정하고, 로그아웃이되면 리다이렉션 될 url도 지정한다.

@EnableWebSecurity 어노테이션에 의해 CSRF 프로텍션이 활성화 된다.

사이트 간 요청 위조(CSRF : Cross Site Request Forgery)는 개발중에는 매우 불편한 기능으로 http에서 https에 대한 요청을 제출하는 등의 상황에서 잘못된 토큰 예외(403)을 발생시킨다.

http.csrf().disable()로 개발중에는 꺼놓는다.


사용자가 A도메인의 서비스에 로그인하면 브라우저에 A서비스의 로그인 관련 쿠키 정보가 남는다.

이후 헤더에 이 정보를 계속 포함시켜서 리퀘스트를 하게 되는데, 동일 브라우저에서 악의적인 코드가 있는 B도메인의 서비스로 접속하게 되면 B서비스의 페이지에는 리퀘스트 헤더에서 이 정보를 얻을 수 있고, 이를 악용하여 A서비스로 임의의 권한이 필요한 리퀘스트를 전송할 수 있게 된다.

CSRF(Cross-Site Request Forgery)는 이런 문제를 해결하기 위해 A 서비스에서 리스폰시 토큰(Token)을 발행하여 그 다음 리퀘스트에 발행된 토큰을 넣어서 리퀘스트하게 하고, 리퀘스트에 헤더에 이 토큰이 없는 경우 권한이 없는 요청으로 인식할 수 있도록 한다.

'Back-end' 카테고리의 다른 글

EL(Expression Language)  (0) 2021.09.05
데이터베이스 프로그래밍  (0) 2021.09.04
스프링 시큐리티  (0) 2021.09.02
JSP의 액션태그  (0) 2021.08.29
JSP의 세션관리  (0) 2021.08.28