admin: custom 메뉴 인가 추가
This commit is contained in:
parent
a153536521
commit
44daa3058b
|
|
@ -4,6 +4,9 @@ import com.bpgroup.poc.admin.security.authentication.CustomAuthenticationEntryPo
|
||||||
import com.bpgroup.poc.admin.security.authentication.CustomAuthenticationFilter;
|
import com.bpgroup.poc.admin.security.authentication.CustomAuthenticationFilter;
|
||||||
import com.bpgroup.poc.admin.security.authentication.CustomAuthenticationProvider;
|
import com.bpgroup.poc.admin.security.authentication.CustomAuthenticationProvider;
|
||||||
import com.bpgroup.poc.admin.security.authentication.service.LoginService;
|
import com.bpgroup.poc.admin.security.authentication.service.LoginService;
|
||||||
|
import com.bpgroup.poc.admin.security.authorization.CustomAccessDeniedHandler;
|
||||||
|
import com.bpgroup.poc.admin.security.authorization.CustomAuthorizationManager;
|
||||||
|
import com.bpgroup.poc.admin.security.authorization.service.AuthorizationService;
|
||||||
import com.bpgroup.poc.admin.security.jwt.JwtTokenConstants;
|
import com.bpgroup.poc.admin.security.jwt.JwtTokenConstants;
|
||||||
import com.bpgroup.poc.admin.security.jwt.JwtTokenValidateFilter;
|
import com.bpgroup.poc.admin.security.jwt.JwtTokenValidateFilter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
@ -35,6 +38,9 @@ public class SecurityConfig {
|
||||||
|
|
||||||
private final LoginService loginService;
|
private final LoginService loginService;
|
||||||
|
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
|
|
@ -48,12 +54,14 @@ public class SecurityConfig {
|
||||||
.cacheControl(cache -> cache.disable()) //ERR_CACHE_MISS
|
.cacheControl(cache -> cache.disable()) //ERR_CACHE_MISS
|
||||||
);
|
);
|
||||||
|
|
||||||
// 인증 설정
|
// 인가 설정
|
||||||
http.authorizeHttpRequests(c -> c
|
http.authorizeHttpRequests(c -> c
|
||||||
.requestMatchers("/css/**", "/images/**", "/js/**", "/font/**", "/favicon.ico").permitAll()
|
.requestMatchers("/css/**", "/images/**", "/js/**", "/font/**", "/favicon.ico").permitAll()
|
||||||
.requestMatchers("/common/modal/**").permitAll()
|
.requestMatchers("/common/modal/**").permitAll()
|
||||||
.requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll()
|
.requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll()
|
||||||
.anyRequest().authenticated());
|
.anyRequest()
|
||||||
|
.access(new CustomAuthorizationManager(authorizationService))
|
||||||
|
);
|
||||||
|
|
||||||
http.formLogin(AbstractHttpConfigurer::disable); // Form 로그인이 아닌 Json 로그인으로 분리
|
http.formLogin(AbstractHttpConfigurer::disable); // Form 로그인이 아닌 Json 로그인으로 분리
|
||||||
http.addFilterBefore(authenticationGenerateFilter(), UsernamePasswordAuthenticationFilter.class); // 로그인 관련 Filter 설정
|
http.addFilterBefore(authenticationGenerateFilter(), UsernamePasswordAuthenticationFilter.class); // 로그인 관련 Filter 설정
|
||||||
|
|
@ -67,6 +75,7 @@ public class SecurityConfig {
|
||||||
|
|
||||||
http.exceptionHandling(c -> {
|
http.exceptionHandling(c -> {
|
||||||
c.authenticationEntryPoint(new CustomAuthenticationEntryPoint()); // Authentication 실패 처리
|
c.authenticationEntryPoint(new CustomAuthenticationEntryPoint()); // Authentication 실패 처리
|
||||||
|
c.accessDeniedHandler(new CustomAccessDeniedHandler()); // Authorization 실패 처리
|
||||||
});
|
});
|
||||||
|
|
||||||
http.logout(c -> c
|
http.logout(c -> c
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package com.bpgroup.poc.admin.security;
|
|
||||||
|
|
||||||
public class SecurityFilterConstants {
|
|
||||||
public static final String[] EXCLUDE_FILTER_STARTS_WITH_URI = {"/login", "/logout", "/error", "/css", "/js", "/images", "/favicon.ico", "/common/modal", "/font"};
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.bpgroup.poc.admin.security.authorization;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||||
|
response.sendRedirect("/error?error=" + URLEncoder.encode("메뉴에 접근할 수 있는 권한이 없습니다.", StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.bpgroup.poc.admin.security.authorization;
|
||||||
|
|
||||||
|
import com.bpgroup.poc.admin.security.authorization.service.AuthorizationService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
|
||||||
|
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext context) {
|
||||||
|
Authentication auth = (Authentication) authentication.get();
|
||||||
|
|
||||||
|
String userName = (String) auth.getPrincipal();
|
||||||
|
String requestUri = context.getRequest().getRequestURI();
|
||||||
|
|
||||||
|
boolean hasAuthorization = authorizationService.isAuthorized(userName, requestUri);
|
||||||
|
|
||||||
|
return new AuthorizationDecision(hasAuthorization);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.bpgroup.poc.admin.security.authorization.service;
|
||||||
|
|
||||||
|
import com.bpgroup.poc.admin.domain.base.admin.entity.Admin;
|
||||||
|
import com.bpgroup.poc.admin.domain.base.admin.entity.AdminRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Transactional
|
||||||
|
public class AuthorizationService {
|
||||||
|
|
||||||
|
private final AdminRepository adminRepository;
|
||||||
|
|
||||||
|
public boolean isAuthorized(String username, String requestUri) {
|
||||||
|
Optional<Admin> findAdmin = adminRepository.findByLoginId(username);
|
||||||
|
if (findAdmin.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Admin admin = findAdmin.get();
|
||||||
|
return admin.getAdminRole().getRole().getRoleMenus().stream()
|
||||||
|
.anyMatch(roleMenu -> roleMenu.getMenu().getUri().equals(requestUri));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue