Files
sake/src/main/java/com/wb/domainserver/security/config/ResourceServerConfig.java

248 lines
12 KiB
Java

/*
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wb.domainserver.security.config;
import com.wb.domainserver.common.prop.PropertyService;
import com.wb.domainserver.domain.sopmal.oauth.service.CustomOAuth2UserService;
import com.wb.domainserver.exception.response.CustomOauthFailureException;
import com.wb.domainserver.realm.RealmResolver;
import com.wb.domainserver.realm.filter.RealmFilter;
import com.wb.domainserver.response.CustomAuthenticationSuccessHandler;
import com.wb.domainserver.security.authentication.CustomAccessDeniedEntryPoint;
import com.wb.domainserver.security.authentication.CustomAuthenticationEntryPoint;
import com.wb.domainserver.security.authorization.WnbtAuthorizationManager;
import com.wb.domainserver.security.filter.BatchFilter;
import com.wb.domainserver.security.filter.CustomXssFilter;
import com.wb.domainserver.security.filter.JwtAuthenticationFilter;
import com.wb.domainserver.security.handler.CustomLogoutSuccessHandler;
import com.wb.domainserver.security.user.SecurityUserDetailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.beans.factory.config.BeanDefinition.ROLE_INFRASTRUCTURE;
@EnableWebSecurity
@Configuration
//@EnableMethodSecurity
public class ResourceServerConfig {
private static final Logger logger = LoggerFactory.getLogger(ResourceServerConfig.class);
@Autowired
private RealmResolver realmResolver;
@Autowired
private SecurityUserDetailService userDetailService;
@Autowired
private CustomAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private CustomAccessDeniedEntryPoint accessDeniedEntryPoint;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private CustomOAuth2UserService customOAuth2UserService;
@Bean
@Role(ROLE_INFRASTRUCTURE)
public Advisor authorizationManagerBeforeMethodInterception(WnbtAuthorizationManager<?> authorizationManager) {
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
pattern.setPattern("com.wb.domainserver.*.controller.*");
return new AuthorizationManagerBeforeMethodInterceptor(pattern, authorizationManager);
}
@Bean
@Order(1)
SecurityFilterChain sopmalSecurityFilterChain(HttpSecurity http, SecurityPathProperties securityProperties) throws Exception {
RequestMatcher logoutRequestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/sopmal/logout")
);
//사용자 권한
List<RequestMatcher> anonymousPath = securityProperties.getSolmal().getAnonmymous().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
List<RequestMatcher> authPath = securityProperties.getSolmal().getAuthenticated().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
List<RequestMatcher> resourcePath = securityProperties.getCommon().getResources().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
OrRequestMatcher anonymoushMatchers = new OrRequestMatcher(anonymousPath);
OrRequestMatcher authMatchers = new OrRequestMatcher(authPath);
OrRequestMatcher resourceMatchers = new OrRequestMatcher(resourcePath);
return http
.securityMatcher("/*", "/sopmal/**", "/oauth2/**", "/login/oauth2/**","/file/*") ///gcone/** #배치호출처리
.headers((headers)->headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize ->
authorize
.requestMatchers(authMatchers).authenticated()
.requestMatchers(anonymoushMatchers).anonymous()
.requestMatchers(resourceMatchers).permitAll()
.requestMatchers(
new AntPathRequestMatcher("/oauth2/**"),
new AntPathRequestMatcher("/login/oauth2/**")
).permitAll()
.anyRequest().permitAll()
)
.oauth2Login(oauth2 -> oauth2 //sns oauth
.loginPage("/sopmal/login")
.successHandler(customAuthenticationSuccessHandler) //인증성공시 로그인 혹은 연동처리
.userInfoEndpoint(userInfo -> userInfo //인증처리
.userService(customOAuth2UserService)
)
.failureHandler(new CustomOauthFailureException()) //인증 실패시
)
.addFilterAfter(new CustomXssFilter(), RequestCacheAwareFilter.class)
.addFilterBefore(new JwtAuthenticationFilter(userDetailService), LogoutFilter.class)
.addFilterAfter(new RealmFilter(realmResolver), HeaderWriterFilter.class)
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedEntryPoint)
).logout(logout
-> logout.logoutRequestMatcher(logoutRequestMatcher)
.deleteCookies("JSESSIONID")
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
)
.build();
}
@Bean
@Order(2)
SecurityFilterChain adminSecurityFilterChain(HttpSecurity http, SecurityPathProperties securityProperties) throws Exception {
// 설정된 로그아웃 URL
RequestMatcher logoutRequestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/mngr/logout"),
new AntPathRequestMatcher("/admin/logout"),
new AntPathRequestMatcher("/crm/logout")
);
List<RequestMatcher> anonmyPath = securityProperties.getAdmin().getAnonmymous().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
List<RequestMatcher> authPath = securityProperties.getAdmin().getAuthenticated().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
List<RequestMatcher> resourcePath = securityProperties.getCommon().getResources().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
OrRequestMatcher authMatchers = new OrRequestMatcher(authPath);
OrRequestMatcher resourceMatchers = new OrRequestMatcher(resourcePath);
return http
.csrf(AbstractHttpConfigurer::disable)
.securityMatcher("/mngr/**","/mngr","/admin/**","/admin","/admin/**","/crm/**","/itrnt/**", logoutRequestMatcher.toString()) //"/*/mq/**", "/api/batch/schedulerloader/**", 제외
.authorizeHttpRequests(authorize ->
authorize
// .requestMatchers(AntPathRequestMatcher.antMatcher("/*/mq/**")).anonymous() //ERP 호출 허용을 위해
// .requestMatchers(AntPathRequestMatcher.antMatcher("/api/batch/schedulerloader/**")).anonymous() //batch 스케줄 동적기동
.requestMatchers(AntPathRequestMatcher.antMatcher("/admin")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/mngr")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/mngr/login/**")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/admin/login/**")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/mngr/tokens/**")).anonymous()
.requestMatchers(AntPathRequestMatcher.antMatcher("/admin/tokens/**")).anonymous()
.requestMatchers(resourceMatchers).permitAll()
.requestMatchers(authMatchers).authenticated()
.anyRequest().permitAll()
)
.addFilterBefore(new JwtAuthenticationFilter(userDetailService), LogoutFilter.class)
.addFilterAfter(new RealmFilter(realmResolver), HeaderWriterFilter.class)
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedEntryPoint)
).logout(logout
-> logout.logoutRequestMatcher(logoutRequestMatcher)
.deleteCookies("JSESSIONID")
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
)
.build();
}
@Bean
@Order(3)
SecurityFilterChain batchSecurityFilterChain(HttpSecurity http, SecurityPathProperties securityProperties) throws Exception {
List<RequestMatcher> uriList = securityProperties.getBatch().getUri().stream()
.map(AntPathRequestMatcher::new)
.collect(Collectors.toList());
OrRequestMatcher uri = new OrRequestMatcher(uriList);
return http
.securityMatcher(uri)
.headers((headers)->headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new BatchFilter(securityProperties), RequestCacheAwareFilter.class) /*batch 호출된 주소 확인 후 주소가 아니면 제외*/
.exceptionHandling(exceptions -> exceptions
.accessDeniedHandler(accessDeniedEntryPoint)
)
.build();
}
//
// private String customBearerTokenResolver(HttpServletRequest request) {
// String authorization = request.getHeader("Authorization");
// if (StringUtils.hasText(authorization) && authorization.startsWith("Bearer ")) {
// return authorization.substring(7);
// }
// return null;
// }
//
// private String determineIssuerUri(String token) {
// return String.format(issuerUri+"/%s", RealmContextHolder.getRealm());
// }
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}