[Start Spring Boot] Spring Security Authorization

·2024년 4월 17일
0

Start Spring Boot!

목록 보기
43/53
post-thumbnail

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 수정

  • SiteUser.java
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로 만들어서 반환하는 방식으로 변환하였다.

회원가입 시 권한부여하기

  • UserController.java
    @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

  • 수 많은 권한을 관리하는 것 보다 역할을 통해서 관리하는 것이 용이하다.
profile
백엔드 개발자가 꿈인 컴공과

0개의 댓글

관련 채용 정보