티스토리 뷰
Spring Advanced : REST + Hibernate with Java Config - CRUD 서비스 인증 추가
Korean Eagle 2020. 5. 23. 00:511. 이 포스트는 아래 링크의 포스트의 연속이다.
2. 이미 구현된 Hibernate기반 REST API에 인증 부분을 추가한다.
2-1 인증 관련 데이터베이스는 스프링 Security 기본스키마를 사용한다.
3. 보안 설정을 위한 Spring Security dependency를 추가한다.
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.verison}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.verison}</version>
</dependency>
4. 보안 설정파일들을 작성한다.
4-1 WebSecurityInitializer 추가
package pe.pilseong.restcrud;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class WebSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
4-2 SecurityConfig 추가
4-2-1 중요한 부분은 보안 관리자설정에서 DaoAuthenticationProvider를 사용하는 부분이다.
4-2-2 DaoAuthenticationProvider는 인증 데이터를 가져오기 위해서 UserDetailsDetail을 사용한다.
4-2-3 인증은 Http Basic을 사용한다. 브라우저를 사용하면 인증 팝업이 화면에 나타난다.
4-2-3-1 postman같은 브라우저 외의 도구를 사용할 때는
4-2-3-2 헤더의 Authorization에 Basic Auth 타입을 설정하고 username, password를 추가해야 한다.
4-2-4 csrf 를 disable한 것은 REST라서 클라이언트가 서버와 다른 곳에 있을 확율이 높아서 이다.
4-2-5 Session Context 설정은 Stateless로 되어 있어 세션을 아예 사용하지 않는다.
4-2-5-1 stateless라도 웹브라우저를 사용하면 비밀번호가 브라우저에 저장되어 매번 인증을 요구하지 않는다.
4-2-5-2 따라서 제대로 설정되었는지 확인할 수가 없다. REST client를 사용하면 정상동작을 확인할 수 있다.
package pe.pilseong.restcrud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/customers").hasRole("EMPLOYEE")
.antMatchers(HttpMethod.GET, "/api/customers/**").hasRole("EMPLOYEE")
.antMatchers(HttpMethod.POST, "/api/customers").hasAnyRole("MANAGER", "ADMIN")
.antMatchers(HttpMethod.POST, "/api/customers/**").hasAnyRole("MANAGER", "ADMIN")
.antMatchers(HttpMethod.PUT, "/api/customers").hasAnyRole("MANAGER", "ADMIN")
.antMatchers(HttpMethod.PUT, "/api/customers/**").hasAnyRole("MANAGER", "ADMIN")
.antMatchers(HttpMethod.DELETE, "/api/customers/**").hasRole("ADMIN")
.and()
.httpBasic()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
5. 사용자를 데이터베이스에서 끌어오므로 Entity 클래스를 만들어야 한다.
5-1 이 프로그램은 스프링 Security의 기본 스키마를 사용하고 있다.
5-1-1 User 클래스다.
package pe.pilseong.restcrud.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "users")
@Data
public class User {
@Id
private String username;
@Column
private String password;
@Column
private boolean enabled;
@OneToMany
@JoinColumn(name = "username")
private List<Authority> authorities;
}
5-1-2 Authority 클래스다.
package pe.pilseong.restcrud.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "authorities")
@Data
public class Authority implements Serializable {
@Id
private String username;
@Id
private String authority;
}
6. 이제 DaoAuthenticationProvider에서 사용할 UserDetailsService 인터페이스를 구현해야 한다.
6-1 UserDetailsService인터페이스를 상속하는 UserService 작성한다. 인증말고는 사용하지 않는다.
package pe.pilseong.restcrud.service;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface UserService extends UserDetailsService {
}
6-2 구현 클래스
6-2-1 Annotation 붙이는 것과 권한 변환부분에 주의한다.
package pe.pilseong.restcrud.service;
import java.util.stream.Collectors;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import pe.pilseong.restcrud.dao.UserDAO;
import pe.pilseong.restcrud.entity.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDAO.loadUserByUsername(username);
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getAuthorities().stream()
.map(role-> new SimpleGrantedAuthority(role.getAuthority()))
.collect(Collectors.toList()));
}
}
7. 사용자 데이터를 가져오는 UserDAO를 구현한다.
7-1 UserDAO 인터페이스
package pe.pilseong.restcrud.dao;
import pe.pilseong.restcrud.entity.User;
public interface UserDAO {
User loadUserByUsername(String username);
}
7-2 UserDAOImpl 클래스
package pe.pilseong.restcrud.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import pe.pilseong.restcrud.entity.User;
@Repository
public class UserDAOImpl implements UserDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public User loadUserByUsername(String username) {
Session session = sessionFactory.getCurrentSession();
return session.get(User.class, username);
}
}
'Spring > Spring Advanced' 카테고리의 다른 글
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- Spring
- one-to-many
- 로그인
- Rest
- spring boot
- Many-To-Many
- login
- 스프링부트
- 매핑
- crud
- 설정
- 외부파일
- WebMvc
- one-to-one
- 스프링
- 상속
- hibernate
- 하이버네이트
- Spring Security
- form
- mapping
- jsp
- RestTemplate
- XML
- Angular
- 설정하기
- Security
- MYSQL
- Validation
- 자바