본문 바로가기

나혼자개발

SpringSecurity 사용방법

주의 스프링부트 버전 2.7.8버전이 아니면 오류가 발생할수있음

 

SecurityConfigure

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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;

// 빈 등록 : 스프링 컨테이너에서 객체를 관리할 수 있게 하는 것

@Configuration //빈등록 (IoC관리)
@EnableWebSecurity //security 필터 등록
@EnableGlobalMethodSecurity(prePostEnabled = true) //특정 주소를 접근을 하면 권한 및 인증을 미리 체크하겠다는 뜻
public class SecurityConfigure {

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration
    ) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean // IoC가 됨
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable() // csrf 토큰 비활성 (테스트시 걸어두는게 좋음)
                .authorizeRequests()
                    .antMatchers("/", "/blog","/auth/**", "/js/**", "/css/**", "/image/**", "/dummy/**", "/board/{id}")
                    .permitAll()
                    .anyRequest()
                    .authenticated()
                .and()
                    .formLogin()
                    .loginPage("/auth/loginForm")
                    .loginProcessingUrl("/auth/loginProc")
                    .defaultSuccessUrl("/"); // 스프링 시큐리티가 해당 주소로 요청오는 로그인을 가로채서 대신 로그인 해준다.
        return http.build();
    }
}

 

PrincipalDetail

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.cos.blog.model.User;

import lombok.Getter;

//스프링 시큐리티가 로그인 요청을 가로채서 로그인을 진행하고 완료가 되면 UserDetails 타입의 오브젝트를
//스프링 시큐리티의 고유한 세션저장소에 저장을 해준다

@Getter		 //private에 있는 user는 원래같으면 Class외부에서 접근할수없다 하지만 @Getter어노테이션을 사용하면 접근할수있다  
public class PrincipalDetail implements UserDetails {
	private User user;  //PrincipalDetail은 User객체를갖고있다 이런걸 콤포지션이라고 한다
	public PrincipalDetail(User user) {
		this.user=user;
	}
	

	@Override
	public String getPassword() {
		return user.getPassword();
	}

	@Override
	public String getUsername() {
		return user.getUsername();
	}
	
	//계정이 만료된지 않았는지 리턴한다.(true:만료안됨)
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}
	
	//계정이 잠겨있지 않았는지 리턴한다.(true:잠기지않음)
	@Override
	public boolean isAccountNonLocked() {
		
		return true;
	}
	//비밀번호가 만료되지않았는지 리턴한다(true:만료안됨)
	@Override
	public boolean isCredentialsNonExpired() {
		
		return true;
	}
	//계정이 활성화(사용가능)인지 리턴한다(true:활성화)
	@Override
	public boolean isEnabled() {
		
		return true;
	}
	
	public void setUser(User user) {
		this.user = user;
	}
	//계정이 갖고있는 권한 목록을 리턴한다.(원래는 권한이여러개있을수있으므로 for문을돌리지만 우리는하나만하겠다)
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		Collection<GrantedAuthority> collectors = new ArrayList<>();
		
		collectors.add(()->{return "ROLE_"+user.getRole();}); //람다식으로 표현한다 GrantedAuthority에는 한개의 메소드밖께없어서
														//자바에서 알잘딱깔센으로 해준다
		return collectors;
	}
	
	

}

 

 

PrincipalDetailService

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;

import com.cos.blog.model.User;
import com.cos.blog.repository.UserRepository;

@Service
public class PrincipalDetailService implements UserDetailsService{
	
	@Autowired
	private UserRepository userRepository;
	
	
	//스프링이 로그인 요청을 가로챌때 username,password 변수 2개를 가로채는데
	//password부분처리는 알아서함
	//그래서 아래코드에서 username이 DB에 있는지 확인해줌
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User principal = userRepository.findByUsername(username)
				.orElseThrow(()->{
					return new UsernameNotFoundException("해당 사용자를 찾을 수 없습니다:"+username);
				});
		// TODO Auto-generated method stub
		return new PrincipalDetail(principal); //이떄 시큐리티의 세션에 유저정보가 저장이된다
	}
	
}

 

세션이 인증되었는지 확인방법

<sec:authorize access="isAuthenticated()">
  <sec:authentication property="principal" var="principal"/>
</sec:authorize>

'나혼자개발' 카테고리의 다른 글

[spring] AOP예시코드  (1) 2024.10.06
만들예정 화면  (0) 2024.07.11
ResponseDto에 들어갈 코드  (0) 2024.07.08
javascript+jquery로 데이터보낼때 예시  (0) 2024.07.08
내가만든 블로그  (0) 2024.07.07