@RestController
public class HomeController {
@RequestMapping("/")
public String index(){
return "홈페이지";
}
기본적인 코드를 작성하여 실행하면 username과 password를 입력하는 화면이 사용자에게 보여진다.
실행하였을 때 Spring에서 제공하는 passoword는 어렵기 때문에
application.yml에서 설정하면 쉽게 인증받을 수 있다.
spring:
security:
user:
name: user1
password: 1111
roles: USER
인증정보를 보고싶을 때
@RequestMapping("/auth")
public Authentication auth(){
return SecurityContextHolder.getContext().getAuthentication();
}
코드를 사용하여 서버를 재실행 하여 들어가면
{
"authorities":[
{
"authority":"ROLE_USER"
}
],
"details":{
"remoteAddress":"127.0.0.1",
"sessionId":"659EBB55CAC42A49EBA2E8F018C2B8D7"
},
"authenticated":true,
"principal":{
"password":null,
"username":"user1",
"authorities":[
{
"authority":"ROLE_USER"
}
],
"accountNonExpired":true,
"accountNonLocked":true,
"credentialsNonExpired":true,
"enabled":true
},
"credentials":null,
"name":"user1"
}
이러한 인증정보를 가지고 사용자가 접근한것을 알수있다.
user와 admin의 개인정보에 해당되는 리소스를 확인해보자
@PreAuthorize("hasAnyAuthority('ROLE_USER')")
@RequestMapping("/user")
public SecurityMessage user() {
return SecurityMessage.builder()
.auth(SecurityContextHolder.getContext().getAuthentication())
.message("User 정보")
.build(); //user의 개인정보를 보여줌
}
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
@RequestMapping("/admin")
public SecurityMessage admin() {
return SecurityMessage.builder()
.auth(SecurityContextHolder.getContext().getAuthentication())
.message("admin 정보")
.build(); //admin의 정보를 보여줌
}
이렇게 실행되면 로그인을 하게되면 user,admin의 정보를 모두 보는것이 가능해저서 정보가 탈취된다.
이러한 현상을 막기위해
package com.example.springsecurity.web.config;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true) //prepost로 권한 확인
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
코드를 작성하여 user가 admin 정보에 접근하려하면
403(Forbidden)에러가 발생한다.
여기서 application.yml에는 사용자를 한명만 설정할 수 있기 때문에 추가로 admin을 등록하기 위한 코드를 작성한다.
package com.example.springsecurity.web.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true) //prepost로 권한 확인
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(User.builder()
.username("user2")
.password(passwordEncoder().encode("2222"))
.roles("USER")
).withUser(User.builder()
.username("admin")
.password(passwordEncoder().encode("3333"))
.roles("ADMIN"));
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
password를 인코딩 해주지않으면 오류가 발생하므로 주의해야 한다.
이렇게되면 또 하나의 문제점이 발생한다.
user1은 로그인을 하지 못한다. 왜냐하면 user에 대한 authentication provider를 추가하면 application.yml의 설정은 더 이상 사용되지 아니한다.
지금까지는 로그인을 해야만 홈페이지가 보이지만 모든 사람들에게
홈페이지는 보여주고 싶다면
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) ->
requests.antMatchers("/").permitAll()
.anyRequest().authenticated());
http.formLogin();
http.httpBasic();
}
코드를 추가하면 된다