Spring Security 1장 간단 구현 최근 스프링부트 메이져 버젼을 업데이트 하며 가장 고생하였던 부분이 있어 집에서 간단하게 정리하고자 샘플 프로젝트를 만들었다. 스프링 부트 버젼 업데이트하며 세션에 저장되어 있는 값이 deserialize가 안되는 현상이 발생하였기 때문이다.
github_code 코드 참고
구성
스프링 시큐리티
레디스 세션
기본 로그인
스프링부트 버젼 2.1.5로 셋팅 -> 2장에서 2.2.4로 변경 예정
build.gradle 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 plugins { id 'org.springframework.boot' version '2.1.5.RELEASE' id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'java' } group = 'com.beanbroker' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.session:spring-session-core' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' compile('org.springframework.session:spring-session-data-redis' ) compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test' ) { exclude group: 'org.junit.vintage' , module : 'junit-vintage-engine' } } dependencyManagement { } test { useJUnitPlatform() }
레디스 연동 아래의 디펜던시 추가
1 implementation 'org.springframework.session:spring-session-core'
docker에서 레디스 띄우기 및 cli 접속1 2 3 docker run -p 6379:6379 --name pkj-redis -d redis redis-cli -h 127.0.0.1 -p 6379
기본 application에 @EnableRedisHttpSession 추가1 2 3 4 5 6 7 8 9 @EnableRedisHttpSession @SpringBootApplication public class BrokerApplication { public static void main (String[] args) { SpringApplication.run(BrokerApplication.class, args); } }
작동확인 방법
대충 컨트롤러를 통해 데이터 넣고 cli를 통해 정상적으로 로우가 쌓였는지 확인1 2 3 4 5 6 7 8 @GetMapping("/test") public void test(HttpSession httpSession){ httpSession.setAttribute("uid", UUID.randomUUID().toString()); Object uid = httpSession.getAttribute("uid"); }
Security설정 아래의 antMatchers등등은 직접 스프링 공홈에서 확인하는 습관을 가지자! 다 떠먹어선 안된다.
스프링 시큐리티 링크
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 32 33 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final BrokerUserService brokerUserService; public SecurityConfig (BrokerUserService brokerUserService) { this .brokerUserService = brokerUserService; } @Bean public PasswordEncoder passwordEncoder () { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Override protected void configure (HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/test" , "/" , "/home" , "/login" , "/create" ).permitAll() .antMatchers("/logout" ).hasRole(UserRole.USER.name()) .antMatchers("/admin" ).hasRole(UserRole.ADMIN.name()) .anyRequest().authenticated() .and() .formLogin() .loginPage("/login" ) .permitAll() .and() .logout(); } }
유저를 만들어보자 아래와 같이 admin과 일반 유저 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @GetMapping ("/set-up" ) public BrokerUserEntity memberJoin () { final BrokerUserEntity user = new BrokerUserEntity(); user.setId(UUID.randomUUID().toString()); user.setUserId("1234" ); user.setPassword(passwordEncoder.encode("1234" )); brokerUserRepository.save(user); final BrokerUserEntity admin = new BrokerUserEntity(); admin.setId(UUID.randomUUID().toString()); admin.setUserId("admin" ); admin.setPassword(passwordEncoder.encode("1234" )); brokerUserRepository.save(user); return user; }
유저 권한 부여 UserDetailsService란? 이것 또한 직접 찾아보자!
id가 admin에 admin role부여 일반유저는 user권한 부여
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 @Service public class BrokerUserService implements UserDetailsService { private final BrokerUserRepository brokerUserRepository; public BrokerUserService (BrokerUserRepository brokerUserRepository) { this .brokerUserRepository = brokerUserRepository; } @Override public UserDetails loadUserByUsername (String username) throws UsernameNotFoundException { BrokerUserEntity user = brokerUserRepository.findBrokerUserByUserId(username); List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); if (username.equals("admin" )) { grantedAuthorities.add(new SimpleGrantedAuthority(UserRole.ADMIN.name())); } else { grantedAuthorities.add(new SimpleGrantedAuthority(UserRole.USER.name())); } return new User(user.getUserId(), user.getPassword(), grantedAuthorities); } }
코드 받고 테스트 방법
localhost:8080/set-up : 아이디 2개 생성
localhost:8080/login : 로그인하자
http://localhost:8080/users : UserDetails 정보
1 2 3 4 5 6 7 8 9 10 11 12 13 { "password" : null , "username" : "1234" , "authorities" : [ { "authority" : "USER" } ], "accountNonExpired" : true , "accountNonLocked" : true , "credentialsNonExpired" : true , "enabled" : true }
너무나도 불칠전한 설명이지만 이 프로젝트는 이게 중요한것이 아니다….