This commit is contained in:
JianChoi-Kor
2022-07-12 00:18:09 +09:00
parent 4f0d70eccb
commit 028dc1125a
6 changed files with 233 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
package com.security.basic.configure;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/static/", "classpath:/public/", "classpath:/", "classpath:/resources/", "classpath:/META-INF/resources/", "classpath:/META-INF/resources/webjars/"
};
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
}

View File

@@ -0,0 +1,20 @@
package com.security.basic.security;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class CustomAuthFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
log.info("exception : " + exception.getMessage());
response.sendRedirect("/login");
}
}

View File

@@ -0,0 +1,20 @@
package com.security.basic.security;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
log.info("authentication : " + authentication.getName());
response.sendRedirect("/home"); //인증이 성공한 후에는 home으로 이동
}
}

View File

@@ -0,0 +1,60 @@
package com.security.basic.security;
import com.security.basic.persistence.dao.UserRepository;
import com.security.basic.persistence.model.Privilege;
import com.security.basic.persistence.model.Role;
import com.security.basic.persistence.model.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
final User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("User Not Found");
}
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), getAuthorities(user.getRoles()));
}
private Collection<? extends GrantedAuthority> getAuthorities(final Collection<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
private List<String> getPrivileges(final Collection<Role> roles) {
final List<String> privileges = new ArrayList<>();
final List<Privilege> collection = new ArrayList<>();
for (final Role role : roles) {
privileges.add(role.getName());
collection.addAll(role.getPrivileges());
}
for (final Privilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(final List<String> privileges) {
final List<GrantedAuthority> authorities = new ArrayList<>();
for (final String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}

View File

@@ -0,0 +1,13 @@
package com.security.basic.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
//securedEnabled @Secured 어노테이션을 사용하여 인가를 처리하고 싶을 때 사용하는 옵션
//prePostEnabled @PreAuthorize, @PostAuthorize 어노테이션을 사용하여 인가를 처리하고 싶을 때 사용하는 옵션
//jsr250Enabled @RolesAllowed 어노테이션을 사용하여 인가를 처리하고 싶을 때 사용하는 옵션
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class MethodSecurity {
}

View File

@@ -0,0 +1,102 @@
package com.security.basic.security;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
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.configuration.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Slf4j
@RequiredArgsConstructor
@Configuration
public class WebSecurityConfigure {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web -> web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations()));
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable();
//요청에 대한 설정
//permitAll시 해당 url에 대한 인증 정보를 요구하지 않는다.
//authenticated시 해당 url에는 인증 정보를 요구한다.(로그인 필요)
//hasAnyRole시 해당 url에는 특정 권한 정보를 요구한다.
// http
// .authorizeRequests()
// .antMatchers("/login", "/home").permitAll()
// .antMatchers("/user").hasAnyRole("USER", "ADMIN")
// .antMatchers("/admin").hasAnyRole("ADMIN")
// .anyRequest().authenticated();
http
.authorizeHttpRequests()
.antMatchers("/**").permitAll();
//로그인폼 관련 설정
//loginPage 로그인 페이지를 설정합니다. 해당 페이지를 설정하지 않으면 Spring Security에서 구현한 디폴트 화면이 노출됩니다.
//defaultSuccessUrl 인가된 사용자일 경우 로그인 성공 후 이동할 페이지를 설정합니다.
//failureUrl 로그인 검증이 실패한 경우 이동할 페이지를 설정합니다.
//successHandler defaultSuccessUrl에서 이동할 페이지만 설정하였다면 handler를 구현하고 이를 등록하면 좀 더 세부적인 작업을 수행할 수 있습니다.
//failureHandler successHandler와 마찬가지로 handler 구현을 통해 더 세부적인 작업을 수행할 수 있습니다.
http
.formLogin()
.defaultSuccessUrl("/home")
.failureUrl("/login?error=true")
// .successHandler(successHandler())
// .failureHandler(failureHandler())
.usernameParameter("email")
.passwordParameter("password");
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login");
//동시 세션 관련 설정
//maximumSessions 최대 허용 가능 세션 수를 설정
//maxSessionPreventsLogin 위에서 설정한 최대 허용 세션의 수가 되었을 때 추가적인 인증이(세션 생성) 있을 경우 어떻게 처리할지 설정
//true일 경우 현재 사용자 인증 실패, false인 경우 기존 세션 만료
//expiredUrl 세션이 만료된 경우 이동할 페이지를 설정정
http
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/expired");
return http.build();
}
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
@Bean
public AuthenticationSuccessHandler successHandler() {
return new CustomAuthSuccessHandler();
}
@Bean
public AuthenticationFailureHandler failureHandler() {
return new CustomAuthFailureHandler();
}
}