일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- sql
- sdk
- sts
- spring
- yml
- 폰트
- YAML
- 배포
- Native
- 이클립스
- Admob
- 시큐리티
- springboot
- thymeleaf
- EAS
- 안드로이드
- 앱
- sqlite
- react
- 로또
- mysql
- expo
- Android
- 자바스크립트
- string
- Java
- 스프링
- 시놀로지
- Navigation
- DB
- Today
- Total
Dev JS Blog
스프링 시큐리티 - 2 (회원 등록) 본문
2023.03.02 - [IT] - 스프링 시큐리티 - 1
URL 권한 주기
스프링 부트 3 버전에 시큐리티도 5.7 이상을 쓰다보니 예전에 했던 방식이랑 조금 달라졌다.
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable() // csrf 중지
.headers().frameOptions().disable()// x-frame-options 중지
.and()
.authorizeRequests()
.requestMatchers( // 원하는 url 패턴 추가
"/h2-console/**", // h2-DB
"/api/member") // 회원가입을 위한 api
.permitAll();
return http.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// web security setting
}
}
H2 접근이 안돼?
security 사용하므로서.. h2-console에 접근도 안되게 된다. 그래서 겨우 찾아낸 결과..
1. crsf disable
2. header frameOptions disable
3. request 허용.
이전 버전과는 다르게 5.7 이상에서는 @Bean 선언해서 설정을 해주면된다.
나는 h2 DB를 사용하기 때문에 h2-console 경로도 추가해줬다.
그리고 api 서버로만 구성할것이기 때문에 로그인페이지나 로그아웃 페이지가 없이
회원 가입을 위한 api/member url만을 추가해줬다.
Member 테이블 생성
@Entity
@Getter
@NoArgsConstructor
public class Member{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String loginId;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String password;
@OneToMany(mappedBy = "member")
private List<MemberRole> roles = Lists.newArrayList();
@Builder
public Member(Long id, String loginId, String name, String password, List<MemberRole> roles) {
this.id = id;
this.loginId = loginId;
this.name = name;
this.password = password;
this.roles = roles;
}
}
Entity 에는 Setter를 쓰지 않는다.(자세한건 김영한님 강의 참고)
나머지는 회원에 대한 기본 정보이고 회원 권한은 MemberRole 이라는 엔티티를 하나 더 구성해서
회원들의 권한을 관리할 생각이다.
그 후 인터페이스인 UserDetails를 구현하면
@Entity
@Getter
@NoArgsConstructor
public class Member implements UserDetails {
// 생략 ...
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = Lists.newArrayList();
// role을 넣어준다.
roles.forEach(role->{
authorities.add(new SimpleGrantedAuthority(role.getRoleType().toString()));
});
return authorities;
}
@Override
public String getUsername() {
return this.loginId; // 계정 아이디를 리턴해준다.
}
@Override
public boolean isAccountNonExpired() { //true면 만료되지 않은 계정
return true;
}
@Override
public boolean isAccountNonLocked() { // true면 잠기지 않은 계정
return true;
}
@Override
public boolean isCredentialsNonExpired() { // true면 비밀번호가 만료되지 않은 계정
return true;
}
@Override
public boolean isEnabled() { // true면 활성화되어있는 계정
return true;
}
}
참고로 getPassword도 있는데 member 클래스에 password가 겹치고 getter가 있다보니 새로 뜨진 않았다.
MemberRole 생성
@Entity
@Getter
public class MemberRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Builder
public MemberRole(Long id, Member member, RoleType roleType) {
this.id = id;
this.member = member;
this.roleType = roleType;
}
}
Member에 OneToMany를 쓰긴 했지만 사실 ManyToOne 구조로만 만드는게 좋다.
하지만 멤버 권한만.. 특별히.. Memeber쪽에 OneToMany를 구성해주었고
MemberRole에는 Member와 조인될 컬럼을 지정해준다.
public enum RoleType {
ROLE_USER,
ROLE_ADMIN
}
그리고 roleType 은 일단 ROLE_USER 와 ROLE_ADMIN 으로 간단하게 구성하겠다.
이렇게 구성하고 서버를 올리면
테이블이 생성된다.
Password Encoder 등록
@Configuration
public class SecurityConfiguration {
// 생략
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
비밀번호 암호화에 사용할 PasswordEncoder를 securityConfiguration에 PasswordEncoder 를 Bean로 등록해준다.
Repository 생성
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
@Repository
public interface MemberRoleRepository extends JpaRepository<MemberRole,Long> {
}
Service 생성
@Service
@RequiredArgsConstructor
@Slf4j
public class MemberService{
private final MemberRepository repository;
private final MemberRoleRepository roleRepository;
private final PasswordEncoder passwordEncoder;
public Long save(MemberRequestDto requestDto) {
String rawPassword = requestDto.getPassword();
String encodePassword = passwordEncoder.encode(rawPassword);
// 멤버 등록 및 ID 가져오기.
Long memberId = repository.save(Member.builder()
.loginId(requestDto.getLoginId())
.name(requestDto.getName())
.password(encodePassword)
.build()).getId();
// 권한 등록
roleRepository.save(
MemberRole.builder()
.member(Member.builder().id(memberId).build())
.roleType(RoleType.ROLE_USER)
.build()
);
return memberId;
}
}
Controller 생성
@RestController
@RequestMapping("/api/member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService service;
@PostMapping
public Long save(MemberRequestDto requestDto){
return service.save(requestDto);
}
}
@Getter
@Setter
public class MemberRequestDto {
private String loginId;
private String name;
private String password;
}
POST localhost:8080/api/member 로 회원 등록 Request를 하면
테이블을 확인하면 Member 테이블에도 잘 쌓였고
MemberRole 테이블에도 권한이 잘 쌓인걸 볼 수 있다.
'IT' 카테고리의 다른 글
Expo Android App 만들기 -1 (2) | 2023.06.07 |
---|---|
Spring Custom Exception, Custom Response (0) | 2023.04.02 |
스프링 H2 DB 사용하기 (0) | 2023.03.05 |
스프링 시큐리티 - 1 (0) | 2023.03.02 |
스프링 프로젝트 초기 Gradle 과 DB 연결 (0) | 2023.03.01 |