Authorization
Authenticaion(인증) vs Authorizaion(인가)
- 인증은 인가보다 먼저 진행된다.
- 인증을 통해 사용자를 구별
- 인가를 통해 권한 및 역할을 부여
권한을 저장하는 곳
- GrantedAuthority() 통해서 저장하고 있다.
- SimpleGrantedAuthority()를 호출하면 권한을 저장함
ROLE vs AUTHORITY
- AUTHORITY은 VIEWPAGE, VIEWADMIN등 하나의 자격을 의미한다.
- ROLE은 ROLE_ADMIN, ROLE_USER등의 일련의 자격이다.
- 여러 AUTHORITY를 묶어서 ROLE로 사용한다.
- ROLE의 경우 반드시 접두사 ROLE_가 필요하다
권한 만들기
- Entity를 만들어서 다른 테이블에서 관리한다.
ROLE, AUTHORITY 만들기
Entity 구성하기
- SiteUser와 ManyToOne 관계를 가진다.
- User는 여러 권한 및 역할을 가질 수 있다.
- Authorities.java
package com.chan.ssb.authority;
import com.chan.ssb.user.SiteUser;
import jakarta.persistence.*;
@Entity
public class Authority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne
@JoinColumn(name = "site_user_id")
private SiteUser siteUser;
private String name;
}
기존 Entity 수정
package com.chan.ssb.user;
import com.chan.ssb.authority.Authority;
import jakarta.persistence.*;
import java.util.Set;
@Entity
public class SiteUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true)
private String username;
private String password;
@OneToMany(mappedBy="siteUser",fetch=FetchType.EAGER)
private Set<Authority> authorities;
}
UserDetailsService 수정하기
- User의 역할을 부여하던 부분을 수정해보자
- UserSecurityService.java
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<SiteUser> _siteUser = this.userRepository.findByusername(username);
if (_siteUser.isEmpty()) {
throw new UsernameNotFoundException("User not found");
}
SiteUser siteUser = _siteUser.get();
return new User(siteUser.getUsername(), siteUser.getPassword(), getGrantedAuthorities(siteUser.getAuthorities()));
}
private List<GrantedAuthority> getGrantedAuthorities(Set<Authority> authorities) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for (Authority authority : authorities) {
grantedAuthorities.add(new SimpleGrantedAuthority(authority.getName()));
}
return grantedAuthorities;
}
- 다음과 같이 권한을 가져와서 List로 만들어서 반환하는 방식으로 변환하였다.
회원가입 시 권한부여하기
@PostMapping("")
public SiteUserDTO createUser(SiteUserDTO userDTO) {
SiteUserDTO createdUser = userService.createSiteUser(userDTO);
if(createdUser != null) {
AuthorityDTO authorityDTO = new AuthorityDTO(0, createdUser.getId(), "ROLE_USER");
authorityService.createAuthority(authorityDTO);
if(createdUser.getUsername().equals("admin")) {
AuthorityDTO adminAuthorityDTO = new AuthorityDTO(0, createdUser.getId(), "ROLE_ADMIN");
authorityService.createAuthority(adminAuthorityDTO);
}
}
return createdUser;
}
- 다음과 같이 성공적으로 회원가입 시 역할을 부여하도록 변경하였다.
- 다음의 코드는 역할을 부여하는 것이고 권한을 부여하고 싶다면 VIEWCARD등으로 변경하면 된다.
- username이 admin인 것에 대하여 ROLE_ADMIN을 부여하였다.
ROLE, AUTHORITY 사용하기
- ROLE: hasRole() / hasAnyRole() / access()
- AUTHORITY: hasAuthority() / hasAnyAuthority() / access()
- 다음의 함수들을 사용하여 설정한다.
AUTHORITY
- SpringSecurityConfiguration.java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests
.requestMatchers("/h2-console/**", "/authority").hasAnyAuthority("VIEWADMIN", "VIEWMANAGER")
.requestMatchers("/api/**").hasAuthority("VIEWAPI")
.requestMatchers("/user/**", "/api-docs","/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**").permitAll()
.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults());
return http.build();
}
- hasAnyAuthority: 설정한 권한 중 어떤 것이라도 가지면 접근 가능
- hasAuthority: 설정한 권한을 가져야 접근 가능
ROLE
- ROLE은 코드에서 사용시 ROLE_ 접두사 없이 사용!
- SpringSecurityConfiguration.java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests
.requestMatchers("/h2-console/**", "/authority").hasRole("ADMIN")
.requestMatchers("/api/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/user/**", "/api-docs","/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**").permitAll()
.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults());
return http.build();
}
- hasAnyRole: 설정한 역할 중 어떤 것이라도 가지면 접근 가능
- hasRole: 설정한 역할을 가져야 접근 가능
ROLE과 Authority
- 수 많은 권한을 관리하는 것 보다 역할을 통해서 관리하는 것이 용이하다.