[Spring Boot] Spring Security

고운·2023년 5월 23일
0

Spring Boot

목록 보기
10/13
post-custom-banner

spring-boot-starter-security dependency를 추가하면 Security가 기본적으로 제공하는 로그인 폼을 사용할 수 있다. 사용자명은 “user”, 암호는 콘솔에 출력된다.

용어

인증(Authentication): 로그인 처리

인가(Authorization): 권한(role) 설정

암호화 인코딩을 위한 객체 생성

@Configuration
public class SpringConfig {
	
	@Bean //객체 제공자
	public PasswordEncoder passwordEncoder() {
		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
	}
}

환경설정

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//메소드 체이닝
		http.authorizeHttpRequests().mvcMatchers("/","/all/**","/signUp").permitAll() //모든 사용자가 접근 가능한 뷰페이지 설정
		.mvcMatchers("/admin/**").hasRole("admin")  //관리자만 접근 가능한 뷰페이지 설정
		.anyRequest().authenticated();  //어떤 요청이든 인증(로그인)되어야 접근 가능
		
		http.formLogin().loginPage("/login").permitAll()
		//모든 사용자에게 로그인 페이지에 접근 허용
		//로그인 페이지 주소는 "/login"
		.defaultSuccessUrl("/service1");
		//로그인 성공하면 service1로 보내기
		
		http.logout()
		.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
		.invalidateHttpSession(true)	//세션 파괴
		.logoutSuccessUrl("/login"); //로그아웃 성공하면 보낼 페이지:login
		
		http.httpBasic(); //나머지는 http 기본 설정을 따름
	}
}

HttpSecurity를 통해 인증과 인가에 대한 설정을 한다.
http.authorizeHttpRequest() -> 반환 타입:AuthorizationManagerRequestMatcherRegistry ->이것을 통해 인증과 인가에 대한 구체적 설정 할 수 있음

mvcMatchers(String ... ):
어떤 요청은 로그인 안해도 되고 어떤 요청은 어떤 롤이어야 하고 그런 패턴들을 써줌

String ...: String 여러개 가능

permitAll(): 아무나 사용 가능

mvcMatchers("/admin/**"): admin이라는 네임스페이스에 있는 모든 요청은
hasRole("admin") : admin이라는 role을 가지고 있어야 요청 가능

anyRequest(): 나머지 서비스들은
authenticated(): 로그인만 하면 됨

메소드 체이닝으로 써줌

환경설정 이것도 있음 (위랑 차이는 모르겠음,…)

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		http.authorizeHttpRequests()
		.requestMatchers("/", "/member/login", "/member/join").permitAll()
		.requestMatchers("/admin/**").hasRole("admin")
		.anyRequest().authenticated();
		
		http.formLogin().loginPage("/member/login").permitAll()
		.defaultSuccessUrl("/board/list/1/all");
		
		http.logout()
		.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
		.invalidateHttpSession(true)
		.logoutSuccessUrl("/member/login");
		
		http.httpBasic();
		
		return http.build();
	}
}

유저 디테일 load

@Service
@Setter
public class MemberService implements UserDetailsService{
		
	@Autowired
	private MemberDAO dao;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		MemberVO m=dao.findById(username);
		if(m==null) {
			throw new UsernameNotFoundException(username);
		}
		UserDetails user=User.builder()
							.username(username)
							.password(m.getPwd())
							.roles(m.getRole()).build();
		return user;
	}
}

회원가입

Form

form에 토큰 삽입

<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }">

Controller

@Autowired
private PasswordEncoder passwordEncoder;
@GetMapping("/signUp")
public void signUpForm() {
	
}

@PostMapping("/signUp")
public ModelAndView signUpSubmit(MemberVO m) {
	ModelAndView mav=new ModelAndView("redirect:/login");
	m.setPwd(passwordEncoder.encode(m.getPwd()));
	int re=-1;
	re=dao.insert(m);
	if (re!=1) {
		mav.setViewName("/all/error");
		mav.addObject("msg","회원가입 실패");
	}
	return mav;
}

로그인

Form

<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }">

Controller

get방식의 뷰만 매핑해주면 됨

@GetMapping("/login")
public void login() {
}

post 방식의 처리는 security가 알아서 해줌

@Controller
public class MemberController {	
	@GetMapping("/service1")
	public void service1(HttpSession session) {
		//인증된(로그인한) 회원의 정보를 갖고 오기 위해 먼저 시큐리티의 인증객체가 필요하다.
		Authentication authentication=
				SecurityContextHolder.getContext().getAuthentication();
		
		//이 인증객체를 통해서 인증된(로그인한) User 객체를 받아온다.
		User user=(User) authentication.getPrincipal();
		
		//이 인증된 User를 통해서 로그인한 회원의 아이디를 갖고온다.
		String id=user.getUsername();
		
		//이 정보를 세션에 상태유지한다.
		//만약 id뿐만 아니라 로그인한 회원의 다른 정보도 필요하다면 dao를 통해 회원의 정보를 가져와서 상태유지한다.
		session.setAttribute("id", id);
	}
}

Controller에서 Model에 상태유지하면 그 다음 페이지에만 유지됨. 계속 유지되게 하려면 session에 상태유지한다.

뷰에서 상태유지된 아이디를 불러올 때: ${id }

profile
백엔드 개발자
post-custom-banner

0개의 댓글