- 현재 사용하는 웹 페이지는 어떠한 경로로 들어가든 Spring Security에서 이를 막고 아래와 같은 로그인 페이지를 보여주고 있습니다.
- 다만 우리는 직접 만들어 놓은 로그인 페이지가 따로 있으며 인증이 필요한 페이지와 그렇지 않은 페이지를 직접 구분하기 위해 Security 설정을 수행해주어야 합니다.
📝 SecurityConfig
- 이를 위해 우선
WebSecurityConfigurerAdapter
를 상속받는 클래스SecurityConfig
를 생성하여 구현해주었습니다.
package com.cos.photogram.config;
...
@EnableWebSecurity //Security 활성화
@Configuration //IoC
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//기존 Security의 기능을 모두 비활성화 시키고 기능을 직접 지정
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/user/**", "image/**", "/subscribe/**", "/comment/**").authenticated() //해당 경로로 접근하기 위해서는 권한이 필요함
.anyRequest().permitAll() //이외의 경로에 대해서는 모두 허용
.and()
.formLogin()
.loginPage("/auth/signin") //로그인 페이지 경로
.defaultSuccessUrl("/"); //로그인에 성공할 시 요청되는 경로
}
}
configure()
메소드는 기존에 Spring Security가 기본적으로 수행하던 기능이 지정되어 있던 메소드로, 이를 수정하고 직접 지정함으로써 Security 설정을 수행할 수 있습니다.
참고: @EnableWebSecurity는 스프링 MVC에서 웹 보안을 활성화하기 위한 어노테이션으로, 핸들러 메소드에서 @AuthenticationPrincipal 어노테이션이 붙은 매개변수를 이용해 인증처리를 수행합니다. 그리고 자동으로 CSRF 토큰을 스프링의 form binding tag library를 사용해 추가하는 빈을 설정합니다.
📝 Controller
- 회원가입을 위한 View 페이지의 일부는 다음과 같이 구성되어 있습니다.
<!--회원가입 인풋-->
<form class="login__input" action="/auth/signup" method="POST">
<input type="text" name="username" placeholder="유저네임" required="required" />
<input type="password" name="password" placeholder="패스워드" required="required" />
<input type="email" name="email" placeholder="이메일" required="required" />
<input type="text" name="name" placeholder="이름" required="required" />
<button>가입</button>
</form>
<!--회원가입 인풋end-->
- 따라서 해당 POST 요청을 받는 Controller를 생성해주기 위해
AuthController
라는 이름의 컨트롤러를 생성하고 아래와 같이 구현해주었습니다.
package com.cos.photogram.web;
...
@RequiredArgsConstructor
@Controller //IoC, 파일을 리턴하는 Controller
public class AuthController {
private final AuthService authService;
//사용자 로그인 페이지 요청
@GetMapping("/auth/signin")
public String signinForm() {
return "auth/signin";
}
//사용자 회원가입 페이지 요청
@GetMapping("/auth/signup")
public String signupForm() {
return "auth/signup";
}
//사용자 회원가입 진행
@PostMapping("/auth/signup")
public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) {
//SignupDto -> User
User user = signupDto.toEntity();
authService.join(user);
return "auth/signin";
}
}
- 이렇게 하면 회원가입 페이지에서 가입 완료 버튼을 누를 시 사용자에게 로그인 페이지가 보여질 것으로 예상하였으나 아래와 같은 오류 페이지가 나타나는 것을 확인할 수 있습니다.
- 결론부터 말하자면 이는 csrf 토큰이 활성화되어 있기 때문인데, 여기서
csrf
란 다른 사이트에서 유저가 보내는 요청을 조작하는 공격. 예시로는 이메일에 첨부된 링크를 누르면 내 은행계좌의 돈이 빠져나가는 방식의 해킹 등을 말합니다. 마찬가지로 회원가입시 페이지를 바꿔치기 하는 등의 방법으로 해킹을 할 수도 있기 때문에 이를 방지하기 위한 것이 csrf 토큰입니다. - 즉, csrf 토큰이란 서버에 들어온 요청이 실제 서버에서 허용한 요청이 맞는지 확인하기 위한 것으로 Spring Security는 이를 해당 페이지에 자동으로 심기 때문에 이를 따로 설정해주지 않으면 위의 오류가 발생하는 것입니다.
- 따라서 우리는 아래와 같은 방법으로 csrf 토큰을 비활성화시킬 수 있습니다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() //csrf 토큰 비활성화
.authorizeRequests()
.antMatchers("/", "/user/**", "image/**", "/subscribe/**", "/comment/**").authenticated() //해당 경로로 접근하기 위해서는 권한이 필요함
.anyRequest().permitAll() //이외의 경로에 대해서는 모두 허용
.and()
.formLogin()
.loginPage("/auth/signin") //로그인 페이지 경로
.defaultSuccessUrl("/"); //로그인에 성공할 시 요청되는 경로
}
📝 참고
https://catsbi.oopy.io/c0a4f395-24b2-44e5-8eeb-275d19e2a536
https://velog.io/@jupiter-j/CSRF%ED%86%A0%ED%81%B0%EC%9D%B4%EB%9E%80
'🚗 Backend Toy Project > Photogram' 카테고리의 다른 글
[Photogram] 회원정보 수정 (0) | 2022.07.09 |
---|---|
[Photogram] 로그인 (0) | 2022.07.08 |
[Photogram] 회원가입 - 공통 응답 DTO, Script 만들기 (0) | 2022.07.08 |
[Photogram] 회원가입 - Validation (0) | 2022.07.07 |
[Photogram] 회원가입 - 데이터베이스 저장 (0) | 2022.07.07 |