Skip to content

Commit 248444a

Browse files
committed
[security-db-auth] FilterInvocationSecurityMetaaataSource 설정 (1)
1 parent df822c8 commit 248444a

File tree

4 files changed

+113
-13
lines changed

4 files changed

+113
-13
lines changed

security-db-auth/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
id 'org.springframework.boot' version '2.2.11.RELEASE'
2+
id 'org.springframework.boot' version '2.3.3.RELEASE'
33
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
44
id 'java'
55
}
@@ -30,6 +30,8 @@ dependencies {
3030
// https://mvnrepository.com/artifact/org.modelmapper/modelmapper
3131
implementation 'org.modelmapper:modelmapper:2.3.0'
3232

33+
developmentOnly 'org.springframework.boot:spring-boot-devtools'
34+
3335
compileOnly 'org.projectlombok:lombok'
3436
annotationProcessor 'org.projectlombok:lombok'
3537

security-db-auth/src/main/java/kr/seok/security/config/SecurityConfig.java

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
import kr.seok.security.form.common.FormAuthenticationDetailsSource;
44
import kr.seok.security.form.handler.FormAccessDeniedHandler;
55
import kr.seok.security.form.provider.FormAuthenticationProvider;
6+
import kr.seok.security.metadatasource.UrlFilterInvocationSecurityMetadataSource;
67
import org.springframework.beans.factory.annotation.Autowired;
78
import org.springframework.beans.factory.annotation.Qualifier;
89
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
910
import org.springframework.context.annotation.Bean;
1011
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.security.access.AccessDecisionManager;
13+
import org.springframework.security.access.AccessDecisionVoter;
14+
import org.springframework.security.access.vote.AffirmativeBased;
15+
import org.springframework.security.access.vote.RoleVoter;
16+
import org.springframework.security.authentication.AuthenticationManager;
1117
import org.springframework.security.authentication.AuthenticationProvider;
1218
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
1319
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -17,9 +23,14 @@
1723
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
1824
import org.springframework.security.crypto.password.PasswordEncoder;
1925
import org.springframework.security.web.access.AccessDeniedHandler;
26+
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
27+
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
2028
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
2129
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
2230

31+
import java.util.Arrays;
32+
import java.util.List;
33+
2334
@Configuration
2435
@EnableWebSecurity
2536
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@@ -57,27 +68,26 @@ public void configure(WebSecurity web) {
5768
protected void configure(HttpSecurity http) throws Exception {
5869
http
5970
.authorizeRequests()
60-
.antMatchers("/", "/users", "/user/login/**").permitAll()
61-
.antMatchers("/mypage").hasRole("USER")
62-
.antMatchers("/messages").hasRole("MANAGER")
63-
.antMatchers("/config").hasRole("ADMIN")
64-
.anyRequest().authenticated()
71+
.antMatchers("/**").permitAll()
72+
.anyRequest().authenticated();
6573

66-
.and()
74+
http
6775
.formLogin()
6876
.loginPage("/login")
69-
/* form 태그의 action url */
70-
.loginProcessingUrl("/login_proc")
71-
/* request의 상세 값을 Details로 추가 하기 위한 작업 */
72-
.authenticationDetailsSource(formAuthenticationDetailsSource)
73-
/* 사용자 정의 Success Handler */
74-
.successHandler(formAuthenticationSuccessHandler)
77+
.loginProcessingUrl("/login_proc") /* form 태그의 action url */
78+
.authenticationDetailsSource(formAuthenticationDetailsSource) /* request의 상세 값을 Details로 추가 하기 위한 작업 */
79+
.successHandler(formAuthenticationSuccessHandler) /* 사용자 정의 Success Handler */
7580
.failureHandler(formAuthenticationFailureHandler)
7681
.permitAll()
7782
;
7883
http
7984
.exceptionHandling()
8085
.accessDeniedHandler(accessDeniedHandler());
86+
87+
/* FilterSecurityInterceptor 사용자 정의 */
88+
http
89+
.addFilterBefore(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class);
90+
8191
http.csrf().disable();
8292
}
8393

@@ -96,4 +106,32 @@ protected void configure(AuthenticationManagerBuilder auth) {
96106
/* 사용자 정의된 Provider 처리 */
97107
.authenticationProvider(authenticationProvider());
98108
}
109+
110+
@Override
111+
public AuthenticationManager authenticationManagerBean() throws Exception {
112+
return super.authenticationManagerBean();
113+
}
114+
115+
@Bean
116+
public FilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource() {
117+
return new UrlFilterInvocationSecurityMetadataSource();
118+
}
119+
120+
@Bean
121+
public FilterSecurityInterceptor customFilterSecurityInterceptor() throws Exception {
122+
FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
123+
filterSecurityInterceptor.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource());
124+
filterSecurityInterceptor.setAccessDecisionManager(affirmativeBased());
125+
filterSecurityInterceptor.setAuthenticationManager(authenticationManagerBean());
126+
return filterSecurityInterceptor;
127+
}
128+
129+
private AccessDecisionManager affirmativeBased() {
130+
return new AffirmativeBased(getAccessDecisionVoters());
131+
}
132+
133+
private List<AccessDecisionVoter<?>> getAccessDecisionVoters() {
134+
return Arrays.asList(new RoleVoter());
135+
}
136+
99137
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package kr.seok.security.metadatasource;
2+
3+
import org.springframework.security.access.ConfigAttribute;
4+
import org.springframework.security.access.SecurityConfig;
5+
import org.springframework.security.web.FilterInvocation;
6+
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
7+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
8+
import org.springframework.security.web.util.matcher.RequestMatcher;
9+
10+
import javax.servlet.http.HttpServletRequest;
11+
import java.util.*;
12+
13+
/**
14+
* Resource와 매핑된 권한 정보 확인용
15+
*/
16+
public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
17+
private LinkedHashMap<RequestMatcher, List<ConfigAttribute>> requestMap = new LinkedHashMap<>();
18+
19+
/**
20+
*
21+
* @param object FilterInvocation
22+
* @return
23+
* @throws IllegalArgumentException
24+
*/
25+
@Override
26+
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
27+
HttpServletRequest request = ((FilterInvocation)object).getRequest();
28+
29+
requestMap.put(new AntPathRequestMatcher("/mypage"), Arrays.asList(new SecurityConfig("ROLE_USER")));
30+
if(requestMap != null) {
31+
for(Map.Entry<RequestMatcher, List<ConfigAttribute>> entry : requestMap.entrySet()) {
32+
RequestMatcher matcher = entry.getKey();
33+
if(matcher.matches(request)) {
34+
/* 권한 정보 */
35+
return entry.getValue();
36+
}
37+
}
38+
}
39+
return null;
40+
}
41+
42+
@Override
43+
public Collection<ConfigAttribute> getAllConfigAttributes() {
44+
Set<ConfigAttribute> allAttributes = new HashSet<>();
45+
46+
for (Map.Entry<RequestMatcher, List<ConfigAttribute>> entry : requestMap.entrySet()) {
47+
allAttributes.addAll(entry.getValue());
48+
}
49+
50+
return allAttributes;
51+
}
52+
53+
@Override
54+
public boolean supports(Class<?> clazz) {
55+
return FilterInvocation.class.isAssignableFrom(clazz);
56+
}
57+
}

security-db-auth/src/main/resources/application.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ spring:
66
enabled: true
77
restart:
88
enabled: true
9+
thymeleaf:
10+
cache: false
11+
912
profiles:
1013
# db 설정 파일, local (logback 설정 파일)
1114
include: db, local

0 commit comments

Comments
 (0)