Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- Javascript
- mybatis
- js
- 자바스크립트기초
- CSS
- 기초 코딩
- 마이바티스
- 코딩
- 자바스크립트 기초
- spring
- 웹앱
- 기초코딩
- 스프링부트
- 구글캘린더api
- 웹
- 리액트세팅
- 자바스크립트
- 처음만나는자바스크립트
- java
- HTML
- 전자정부 서버세팅
- 구글 oauth
- 자바스크립트기초문법
- 리액트초기세팅
- 자바
- react
- Spring Boot
- 리액트프로젝트세팅
- springboot
- javaspring
Archives
- Today
- Total
인생 디벨로퍼
Spring security + my batis 본문
728x90
시큐리티, 스프링 업그레이드로 변경된 부분이 있어 정리해두려 함.
그래들 버전 디펜던시 dependencies
implementation "org.springframework.boot:spring-boot-starter-security"
지금 과정에서 테스트는 진행하지 않을 예정이라 추가하지 않음.
SecurityConfig
package com.jycoding.login.config;
import jakarta.servlet.DispatcherType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity
@Configuration // Bean 을 정의
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) //secured 활성화(실행 후), preAutorize 활성화(실행 전)
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// h2 콘솔 사용을 위한 설정
http.csrf((csrf) -> csrf
.ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**")))
.headers((headers) -> headers.addHeaderWriter(new XFrameOptionsHeaderWriter(
XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)));
// disable 하지 않으면 post, delete 요청을 막아버림
http.csrf((csrf-> csrf.disable()));
http.authorizeHttpRequests((authorize) -> {
authorize
.dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
.requestMatchers("/user").hasAnyAuthority("USER")
.requestMatchers("/admin").hasAnyAuthority("ADMIN")
.requestMatchers("/**").permitAll()
.anyRequest().permitAll();
});
// 로그인 페이지는 loginForm 으로 설정, 기존 로그인 페이지가 아닌 직접 생성한 로그인 페이지로 보낸다.
http.formLogin(form -> form.loginPage("/loginForm")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/"));
return http.build();
}
// 권한 계층 설정 (어드민 > 유저 -> 어드민이 유저의 모든 권한을 상속받는다)
@Bean
static RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ADMIN > USER\n");
return hierarchy;
}
// 메소드 수준의 보안 실행 -> 메소드가 호출될때 보안 검사를 수행
@Bean
static MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
// 비밀번호 인코딩
@Bean
BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
auth/PrincipalDetails
package com.jycoding.login.config.auth;
import com.jycoding.login.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
// Security Session => Authentication => UserDetails(PrincipalDetails)
@Slf4j
public class PrincipalDetails implements UserDetails {
private User user;
public PrincipalDetails(User user) {
this.user = user;
}
// 해당 유저의 권한을 리턴하는 곳
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collect = new ArrayList<>();
collect.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole();
}
@Override
public String toString() {
return getAuthority();
}
});
// [ROLE_ADMIN]
log.info(collect.toString());
return collect;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
//계정 만료 여부
@Override
public boolean isAccountNonExpired() {
return true;
}
// 계정 잠겼는지
@Override
public boolean isAccountNonLocked() {
return true;
}
// 자격증면이 만료 되었는지
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 계정 활성화 (비활시 false 반환)
@Override
public boolean isEnabled() {
return true;
}
}
auth/PrincipalDetailsService
package com.jycoding.login.config.auth;
import com.jycoding.login.model.User;
import com.jycoding.login.model.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
// "/login" 요청이 오면 자동으로 UserDetailsService 타입을 IoC 되어 있는 loadUserByUsername 함수가 실행
@Service
@Slf4j
public class PrincipalDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
// 시큐리티 session 내부(Authentication 내부 (UserDetails))
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
//User(id=1, username=ssar, password=$2a$10$pszt9sAg3yXLmy1XxZEjkeXOwJY0hMqhifao3hgwnqZ9XVb/7p.cm, role=ROLE_ADMIN, email=쌀, createdAt=2024-03-08 15:28:20.104208)
log.info(userEntity.toString());
if (userEntity != null){
return new PrincipalDetails(userEntity);
}
return null;
}
}
회원가입 컨트롤러에서 추가해야하는 코드
joinReqDto.setRole("USER");
String encPassword = bCryptPasswordEncoder.encode(joinReqDto.getPassword());
joinReqDto.setPassword(encPassword);
userService.회원가입(joinReqDto);
이때, role 에 "ROLE_" 접두어를 붙어야 한다, 아니다로 갈리는데,
직접 해본 결과 필요 없었다. 두가지 다 작동 잘 됨.
이후 JWT 부분도 보완해서 업로드 예정.
728x90
'JAVA Spring' 카테고리의 다른 글
[Google API] 구글 캘린더 일정 List 불러오기 (0) | 2024.11.01 |
---|---|
[Google API] 구글 캘린더 프로젝트 생성, api 키 생성 (0) | 2024.10.30 |
myBatis 검색 연습, 검색 쿼리 (.feat 페이징) (0) | 2023.06.23 |
myBatis 페이징 연습 (0) | 2023.06.20 |
Cookie 아이디 저장하기 (0) | 2023.06.18 |