스프링 시큐리티에 대한 이해
스프링 기반 어플리케이션의 보안( 인증과 권한 )을 담당하는 프레임워크이다.
스프링 시큐리티는 보안과 관련해서 체계적으로 많은 옵션들로 이를 지원해준다.
spring security는 filter 기반으로 동작하기 때문에 spring MVC 와 분리되어 관리 및 동작한다.
스프링 시큐리티에 대한 키워드
접근 주체 ( Principal ) : 보호된 대상에 접근하는 클라이언트
인증 ( Authentication ) : 현재 유저가 누구인지 확인 / 애플리케이션의 작업을 수행할 수 있는 주체임을 증명하는 과정
ex ) HTTP Basic Authentication 폼 로그인
인가 ( Authorize ) : 현재 유저가 어떤 서비스, 페이지에 접근할 수 있는 권한이 있는지 검사
권한 ( Authorization ) : 인증된 주체가 애플리케이션의 동작을 수행할 수 있도록 허락되있는지를 결정
Spring security structure
스프링 시큐리티 시작하기
dependencies {
compile 'org.springframework.security:spring-security-web:4.2.2.RELEASE'
compile 'org.springframework.security:spring-security-config:4.2.2.RELEASE'
}
java configuration
스프링 시큐리티 xml 기반 설정에서는 springSecurityFilterChain 을 등록하는 것으로 시작하지만
자바기반 설정에서는 WebSecurityConfigurerAdapter를 상속받은 클래스에
@EnableWebSecurity 어노테이션을 명시하는 것만으로도 springSecurityFilterChain가 자동으로 포함되어 진다.
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
HttpSecurity
configure 메소드를 통해서 커스텀 인증 매커니즘을 구성할 수 있다.
public class SecurityConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
.authorizeRequests() : 요청에 대한 권한을 지정할 수 있다.
.anyRequest().authenticated() : 인증이 되어야 한다는 이야기이다.
.anonymous() : 인증되지 않은 사용자도 접근할 수 있다.
.fullyAuthenticated() : 완전히 인증된 사용자만 접근할 수 있다.
.hasRole() or hasAnyRole() : 특정 권한을 가지는 사용자만 접근할 수 있다.
.hasAuthority() or hasAnyAuthority() : 특정 권한을 가지는 사용자만 접근할 수 있다.
.hasIpAddress() : 특정 아이피 주소를 가지는 사용자만 접근할 수 있다.
.access() : SpEL? 표현식에 의한 결과에 따라 접근할 수 있다.
.not() : 접근 제한 기능을 해제
.permitAll() or denyAll() : 접근을 전부 허용하거나 제한한다.
.rememberMe() : 로그인한 사용자만 접근할 수 있다. 리멤버기능
Method Security
스프링 스큐리티는 다음과 같이 인터페이스에 시큐리티를 걸어 줄수도 있다.
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
// ...
}
public interface BankService {
@PreAuthorize("isAnonymous()")
public Account readAccount(Long id);
@PreAuthorize("isAnonymous()")
public Account[] findAccounts();
@PreAuthorize("hasAuthority('ROLE_TELLER')")
public Account post(Account account, double amount);
}
Remember-Me
UserDetails & UserDetailsService
public class UserDetails extends org.springframework.security.core.userdetails.User {
private static final long serialVersionUID = -4855890427225819382L;
private Long id;
private String nickname;
private String email;
private Date createdAt;
public UserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
// TODO Auto-generated constructor stub
}
public UserDetails(User user){
super(user.getEmail(), user.getPassword(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isCredentialsNonExpired(), user.isEnabled(), authorities(user));
this.id = user.getId();
this.nickname = user.getNickname();
this.email = user.getEmail();
this.createdAt = user.getCreatedAt();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
private static Collection<? extends GrantedAuthority> authorities(User user) {
// TODO Auto-generated method stub
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
user.getAuthorities().forEach(a -> {
authorities.add(new SimpleGrantedAuthority(a.getAuthority()));
});
return authorities;
}
public UserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities,
String nickname) {
super(username, password, authorities);
this.nickname = nickname;
this.email = username;
}
public UserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
// TODO Auto-generated constructor stub
}
}
Password Encoding
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Service
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
// TODO Auto-generated method stub
User user = userRepository.findByEmail(email);
if(user == null){
throw new UsernameNotFoundException(email);
}
com.kdev.app.security.userdetails.UserDetails userDetails = new com.kdev.app.security.userdetails.UserDetails(user);
return userDetails;
}
}
AuthenticationSuccessHandler & AuthenticationFailureHandler
클라이언트가 인증과정을 성공했을때와 실패했을 경우 handler 를 implementaion 해서 custom 할 수 있다.
public class AuthenticationSuccessHandlerImpl extends SavedRequestAwareAuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessHandlerImpl.class);
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
logger.info("Login Success... - {}", authentication.getPrincipal());
response.sendRedirect("/?login");
}
}
public class AuthenticationFailureHandlerImpl extends SimpleUrlAuthenticationFailureHandler {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationFailureHandlerImpl.class);
public AuthenticationFailureHandlerImpl() {
this.setDefaultFailureUrl("/login?error");
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
logger.info("Login Failed... - {}",request.getParameter("email"));
super.onAuthenticationFailure(request, response, exception);
}
}
'개발 > spring' 카테고리의 다른 글
13장 웹 어플리케이션과 영속성 관리 (0) | 2019.04.18 |
---|---|
spring oauth2.0 jwt 토큰 방식 (5) | 2019.01.21 |
spring OAuth server 구성 (0) | 2019.01.10 |
spring 이란 무엇인가 (0) | 2018.12.09 |
rabbitmq microservice 스프링 부트 (0) | 2018.11.28 |
댓글