Spring-boot + security 설정 -1
가장 기본적인 형태의 스프링 시큐리티 설정에서 부터 내가 원하는 기능으로 바꿀때까지
하나씩 기록을 목적으로 이렇게 또 적어둔다.
일단 스프링 스타터로 아무것도 안해도 이렇게 화면이 뜬다.
'순간 머지?' 암호랑 패쓰는 머지?!!
그랬다가 좀 찾아보니
콘솔에 이렇게 뜨길래 다시 또 ' 그럼 id ? ' 하면 몇 개 트라이해보니 "user" 임을 깨닫게 되었다.
이제 그럼 내가 만든 사용자 DB 로 로그인하려면 어떻게 하지?
일단 위 글이 괜찮아 보여서 읽기 시작
(10분 후 ) 음... 나의 의식의 흐름과 다른 흐름이라 그런지.. 잘 모르것다.. 다시 검색 시작
http://progtrend.blogspot.com/2018/07/spring-boot-security.html
위 글이 도움이 젤 많이 됐다.
1. 인증프로바이더 설정 (= 내가 정의한 db 로 id/pass 매칭 체크 어떻게 할껀지?)
package com.cube.login.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.cube.login.dao.LoginMapper;
import com.cube.model.UserVo;
@Component
public class AuthProvider implements AuthenticationProvider {
@Autowired
LoginMapper loginMapper;
@Autowired
PasswordEncoder pwdEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String id = authentication.getName();
UserVo user = loginMapper.getUser(id);
// 유저 없는경우
if (null == user ) {
return null;
}
// 비번 불일치
if (!pwdEncoder.matches(authentication.getCredentials().toString(), user.getPassword())) {
throw new BadCredentialsException("Wrong password");
}
List<GrantedAuthority> grantedAuthorityList = new ArrayList<>();
grantedAuthorityList.add(new SimpleGrantedAuthority(user.getAuth()));
// 로그인 성공시 로그인 사용자 정보 반환
return new UsernamePasswordAuthenticationToken(user, null, grantedAuthorityList);
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
2. SpringSecurity Config 클래스 추가
package com.cube.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.cube.login.service.AuthFailureHandler;
import com.cube.login.service.AuthProvider;
import com.cube.login.service.AuthSuccessHandler;
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
AuthProvider authProvider;
@Autowired
AuthFailureHandler authFailureHandler;
@Autowired
AuthSuccessHandler authSuccessHandler;
@Override
public void configure(WebSecurity web) throws Exception {
// 허용되어야 할 경로들
web.ignoring().antMatchers("/resources/**",
"/dist/**",
"/css/**",
"/font-awesome/**",
"/fonts/**",
"/img/**",
"/js/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 로그인 설정
http.authorizeRequests()
.antMatchers("/", "/user/login","/user/admin", "/error**").permitAll()
// ROLE_USER, ROLE_ADMIN으로 권한 분리 유알엘 정의
.antMatchers("/**").access("ROLE_USER")
.antMatchers("/**").access("ROLE_ADMIN")
.antMatchers("/admin/**").access("ROLE_ADMIN")
.antMatchers("/**").authenticated();
http
// 로그인 페이지 및 성공 url, handler 그리고 로그인 시 사용되는 id, password 파라미터 정의
.formLogin()
.loginPage("/user/login")
.loginProcessingUrl("/authenticate")
.defaultSuccessUrl("/")
.usernameParameter("id_user")
.passwordParameter("password");
http
// 로그아웃 관련 설정
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.csrf()
.csrfTokenRepository(new CookieCsrfTokenRepository())
.and()
// 로그인 프로세스가 진행될 provider
.authenticationProvider(authProvider);
}
}
3. 로그인 JSP 페이지
: csrf 문제인지 첨에 모르고 무한 403 에러를 만났다 ㅠㅠ.
JSP 로 하려면 hidden ${_csrf.parameterName} 에 값을 같이 post 로 쏴줘야 한다.
<form class="m-t" role="form" action="/authenticate" method="POST">
<div class="form-group">
<input type="text" name="id_user" class="form-control" placeholder="Username" required="">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="Password" required="">
</div>
<button type="submit" class="btn btn-primary block full-width m-b">Login</button>
<a href="#"><small>Forgot password?</small></a>
<p class="text-muted text-center"><small>Do not have an account?</small></p>
<a class="btn btn-sm btn-white btn-block" href="register.html">Create an account</a>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
csrf 와 관련한 건
https://reiphiel.tistory.com/entry/spring-security-csrf
위 링크가 설명이 젤 이해가 쉬웠다.
그런데 typthymeleaf 를 쓰면 자동으로 hidden 으로 심어 준다고 하니.. 써봐야겠다.