248 lines
12 KiB
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();
|
|
}
|
|
}
|