본문 바로가기
spring | spring boot/오류 해결

springboot - spring security 기억할것 (내가..)

by socialcomputer 2022. 4. 13.
반응형

내가 자꾸 빼먹어서 삽질하길래 정리해두는 spring security 사용할때 한 자잘한 실수들..

회원가입 부분에서 user db에 아무것도 저장이 안되고, controller도 작동하지 않는 문제가 있었다. 

거의 몇주를 붙잡고 있었지만... 정작 이유는 간단했다.  - 아래 더보기 클릭하면 이유 보임

더보기

<참고로 내가 왜이렇게 오래 삽질을 했는가?> -까먹지 않기 위해 적어두는 문제 상황

 

허용되지 않은 url을 요청하면 스프링시큐리티에서 loginForm페이지를 보여주는데 

회원가입시 join으로 form을 보내면 컨드롤러에서 redirect:loginForm 하라고 설정했기 때문에 

문제가 뭔지 알아치리지 못했었다. 

이와 비슷한 문제가 있었기에 알아차릴 수 있었는데, 아래 링크에서 확인할 수 있다. 

2022.03.31 - [spring | spring boot/오류 해결] - SpringBoot - security : localhost에서 리디렉션한 횟수가 너무 많습니다.

 

form 태그로 회원가입을 post방식으로 보내줄때 action에 지정한 url을 시큐리티설정에서 permitAll() 해주지 않았기 때문이다. 혹은 anonymous() 헤주거나

permitAll() 은 지정한 페이지에 모든 접근을 허용
anonymous() 는 지정한 페이지에 인증되지 않은 접근만 허용한다. 예를 들면 로그인한 상태로는 회원가입을 못하게 하는 경우.

 

아래처럼 티임리프를 사용해서 폼을 만든 상태였다. ( th:action을 쓰면 csrf토큰을 신경쓰지 않아도 된다고 한다. )

<form th:action="@{/join}" method="post">
        <!-- th:action 쓰면 csrf 토큰 전송 안해도 됨
        <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
         -->
    <div class="form-floating">
	    <input type="text" class="form-control" name="username" id="username" placeholder="username">
	    <label for="floatingPassword">username</label>
    </div>
	<div class="form-floating">
	    <input type="email" class="form-control" name="email" id="floatingInput" placeholder="name@example.com">
		<label for="floatingInput">name@example.com</label>
	</div>
	<div class="form-floating">
		<input type="password" class="form-control" name="password" id="floatingPassword" placeholder="Password">
		<label for="floatingPassword">password</label>
	</div>
         
  
<button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
</form>

 

완성된 시큐리티 설정 클래스

@RequiredArgsConstructor
@Configuration //configuration 에서 AllArgsConstructor가 빠져서 bean등록 오류가 생성됨 -> @AllArgs..추가
@EnableWebSecurity//스프링 시큐리티 필터가 필터체인에 등록이 됨
public class SecurityConfig extends WebSecurityConfigurerAdapter{
	final private PrincipalOAuth2UserService principalOAuth2UserService;

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.authorizeRequests()
		.antMatchers("/",
					"/login","/loginForm",
					"/project/list",
					"/join").permitAll() // 모두 허용
		.antMatchers("/css/**/*", "/scripts/**/*").permitAll()
		.antMatchers("/joinForm").anonymous() // 인증되지 않은 자만 접근(인증자접근 안됨)
		.antMatchers("/project/write",
					"/project/view/**").authenticated() // 인증만 되면 들어갈 수 있음
		.antMatchers("/api/**").permitAll()
		.antMatchers(
                "/v3/**",
                "/v2/**",
                "/swagger*/**").permitAll()
		.antMatchers("/h2-console/**").permitAll()
        .anyRequest().authenticated() // 이외의 모든 request들은 인증이 되어야만 한다
		.and()
				.formLogin()
				.loginPage("/loginForm")
				.usernameParameter("username")/*default=username*/
				.loginProcessingUrl("/login")
				.defaultSuccessUrl("/")
		.and()
				.oauth2Login()
				.loginPage("/loginForm")
				.userInfoEndpoint()
				.userService(principalOAuth2UserService);
		
		// http.csrf().ignoringAntMatchers("/h2-console/**"); // 이전코드
		http.headers().frameOptions().disable();
		/* h2-console 은 iframe을 사용.
		* Spring security를 사용하면 http header에 X-Frame-Options가 추가되어
		* iframe으로 동작하던 기능이 정상적으로 동작하지 않아 생겼던 현상이었으며
		* 위의 코드는 X-Frame-Options header를 추가하는 부분을 비활성화한 것
		*/

	}

	/**
	 * 비밀번호 암호화시키는 객체 ioc등록
	 */
	@Bean
	static BCryptPasswordEncoder encodePwd(){
		return new BCryptPasswordEncoder();
	}

}

 

결론

spring security를 적용했을땐
새로운 페이지를 생성하거나 경로를 수정할 때마다 security configure를 같이 업데이트 해줘야 한다. 
아니면 처음엔 모든 페이지를 permitAll 했다가 구현이 다 끝났을때 세세히 지정해줘야 겠다. 

 

반응형

댓글