(spring)스프링 시큐리티

전성영·2022년 5월 24일
0

spring

목록 보기
8/31

스프링 시큐리티란?

스프링 시큐리티 프레임워크는 스프링 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 준다.

프레임워크 추가

implementation 'org.springframework.boot:spring-boot-starter-security'

-build.gradle-


package com.sparta.week04.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure (WebSecurity web){
        // h2-console 사용에 대한 허용 (CSRF, FrameOptions 무시)
        web.ignoring().antMatchers("/h2-console/**");
    }

    @Bean
    public BCryptPasswordEncoder encodePassword() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 회원 관리 처리 API (POST /user/**) 에 대해 CSRF 무시
        http.csrf().ignoringAntMatchers("/user/**");

        http.authorizeRequests()
                    // image 폴더를 login 없이 허용
                    .antMatchers("/images/**").permitAll()
                    // css 폴더를 login 없이 허용
                    .antMatchers("/css/**").permitAll()
                    //회원 관리 처리 API 전부를 login 없이 허용
                    .antMatchers("/user/**").permitAll()

                     // 어떤 요청이든 '인증'
                     .anyRequest().authenticated()
                .and()

                    // 로그인 기능 허용
                    .formLogin()

                    //로그인 View 제공(GET/user/login)
                    .loginPage("/user/login")   //로그인 할 때 longin.html 페이지로
                    // 로그인 처리 (POST/user/login)
                    .loginProcessingUrl("/user/login")  //로그인 처리(보안검색대 가고 그런 과정들)

                    .defaultSuccessUrl("/")     //로그인이 성공할 시 해당 url로 이동
                    .failureUrl("/user/login?error")    //실패했을 때 url
                    .permitAll()//로그인에 관련된 기능에 대해 허용을 해줘라
                .and()

                    // 로그아웃 기능 허용
                    .logout()
                    // 로그아웃 처리 URL
                    .logoutUrl("/user/logout")
                    .permitAll();           //로그아웃에 관련된 기능에 대해 허용을 해줘라
    }
}

-WebSecurityConfig.java-
허용을 해주는 부분이 중요한 것 같다.

package com.sparta.week04.security;

import com.sparta.week04.domain.Users;
import com.sparta.week04.repository.UserRepository;
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;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {     //Spring Security에서 유저의 정보를 가져오는 인터페이스이다.

    private final UserRepository userRepository;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    //loadUserByUsername 는 UserDetailsService가 가지고 있는 함수
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Users user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("Can't find " + username));
        //조회가 되면 UserDetail로 반환?
        return new UserDetailsImpl(user);
    }
}

-UserDetailsServiceImpl.java-

UserDetailsService라는 인터페이스를 implements 해준다.

UserDetailsService 이 친구는 loadUserByUsername() 이라는 함수를 가지고 있고, 필수적으로 선언을 해줘야 한다고 한다.

user의 정보를 찾으면 UserDetailsImpl 로 넘겨준다.

package com.sparta.week04.security;
import com.sparta.week04.domain.Users;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;

public class UserDetailsImpl implements UserDetails {   //Spring Security에서 사용자의 정보를 담는 인터페이스이다.?


    private final Users user;

    public UserDetailsImpl(Users user) {    //userDatialsService에서 조회가 된 회원 정보의 객체
        this.user = user;
    }

    public Users getUser() {
        return user;
    }

    @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;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    //
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.emptyList();
    }
}

-UserDetailsImpl.java-

public UserDetailsImpl(Users user) {
   this.user = user;
}

조회가 된 회원 정보를 넣는다.

그 후 사용을 하려면

@Controller
public class HomeController {
    @GetMapping("/")
    public String home(Model model, @AuthenticationPrincipal UserDetailsImpl userDetails) { 
        model.addAttribute("username", userDetails.getUsername());
        return "index";
    }
}

-HomeController.java-

@AuthenticationPrincipal UserDetailsImpl userDetails 에서
userDetails 에 사용자의 정보가 담기고, index.html 이라는 곳에 username 에 로그인 된 사용자의 이름을 전달해준다.

흐름을 좀 잡기위해 크게크게 써보았다. 틀린 부분은 더 공부하면서 고칠 예정이다.
끗!

!!!!!!!!!!!!!

회원가입을 진행할 때 클라에서 POST로 받은 정보들을 controller 안에 있는 SignupRequestDto에 담아 서버로 넘어오는데, 그 정보들을 service 안에 있는 registerUser 함수에 넣어준다.
이 service 단에서 패스워드 암호화, 관리자/사용자 등 정해준 후 repo에 저장한다.

profile
Slow and Steady

0개의 댓글