1 package cn.home1.oss.lib.security.starter;
2
3 import static cn.home1.oss.boot.autoconfigure.AppType.RESOURCE;
4 import static com.google.common.collect.Lists.newArrayList;
5 import static com.google.common.collect.Sets.newLinkedHashSet;
6 import static java.util.stream.Collectors.groupingBy;
7 import static java.util.stream.Collectors.mapping;
8 import static java.util.stream.Collectors.toList;
9 import static org.apache.commons.lang3.StringUtils.isBlank;
10 import static org.apache.commons.lang3.StringUtils.isNotBlank;
11
12 import com.google.common.collect.ImmutableMap;
13
14 import cn.home1.oss.boot.autoconfigure.AppProperties;
15 import cn.home1.oss.boot.autoconfigure.AppSecurityProperties;
16 import cn.home1.oss.lib.security.internal.VerifyCodeFilter;
17
18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties;
20 import org.springframework.boot.autoconfigure.security.SecurityProperties;
21 import org.springframework.boot.autoconfigure.security.SpringBootWebSecurityConfiguration;
22 import org.springframework.context.annotation.Bean;
23 import org.springframework.context.annotation.Configuration;
24 import org.springframework.core.annotation.Order;
25 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
26 import org.springframework.security.config.annotation.web.builders.WebSecurity;
27 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
28 import org.springframework.security.web.util.matcher.AnyRequestMatcher;
29 import org.springframework.security.web.util.matcher.OrRequestMatcher;
30 import org.springframework.security.web.util.matcher.RequestMatcher;
31
32 import java.util.Collection;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37
38
39
40
41
42 @Order(PermitedRequestConfiguration.ORDER_PERMITED_REQUEST)
43 @Configuration
44 public class PermitedRequestConfiguration extends SecurityConfigurerAdapter<PermitedRequestConfiguration> {
45
46 public static final String PERMITED_REQUESTS = "permitedRequests";
47 public static final String PERMITED_REQUEST_MATCHER = "permitedRequestMatcher";
48
49 public static final int ORDER_PERMITED_REQUEST = SecurityProperties.IGNORED_ORDER + 1;
50
51 @Autowired
52 private AppProperties appProperties;
53
54 @Autowired(required = false)
55 private VerifyCodeFilter verifyCodeFilter;
56
57 @Autowired(required = false)
58 private H2ConsoleProperties h2ConsoleProperties;
59
60 @Override
61 public void init(final WebSecurity web) {
62 final Set<String> ignored = newLinkedHashSet();
63
64
65
66
67
68
69
70 ignored.add("/h2-console/**");
71 if (this.h2ConsoleProperties != null) {
72 final String path = this.h2ConsoleProperties.getPath();
73 final String antPattern = (path.endsWith("/") ? path + "**" : path + "/**");
74 ignored.add(antPattern);
75 }
76
77
78 if (!ignored.isEmpty()) {
79 final List<RequestMatcher> matchers = ignored.stream()
80 .map(pattern -> new AntPathRequestMatcher(pattern, null))
81 .collect(toList());
82 final RequestMatcher requestMatcher = new OrRequestMatcher(matchers);
83 web.ignoring().requestMatchers(requestMatcher);
84 }
85 }
86
87 @Override
88 public void configure(final HttpSecurity http) {
89
90 }
91
92 @Bean(name = PERMITED_REQUEST_MATCHER)
93 public RequestMatcher permitedRequestMatcher() {
94 final RequestMatcher result;
95 if (this.appProperties.getSecurityEnabled()) {
96
97 final List<RequestMatcher> antMatchers = this.permitedRequests().entrySet().stream()
98 .flatMap(entry -> entry.getValue().stream().map(pattern ->
99 isBlank(entry.getKey())
100 ? new AntPathRequestMatcher(pattern) : new AntPathRequestMatcher(pattern, entry.getKey())
101 )).collect(toList());
102 result = antMatchers.isEmpty() ? request -> false : new OrRequestMatcher(antMatchers);
103 } else {
104 result = AnyRequestMatcher.INSTANCE;
105 }
106 return result;
107 }
108
109 @Bean(name = PERMITED_REQUESTS)
110 public Map<String, List<String>> permitedRequests() {
111
112 final AppSecurityProperties security = this.appProperties.getSecurity();
113
114 final String loginPage = security.getLoginPage();
115
116 final Collection<String> defaultPermited = this.appProperties.getType() != RESOURCE ?
117 newLinkedHashSet(newArrayList(
118 security.getLoginPublicKeyUrl(), loginPage, security.getLoginProcessingUrl(),
119 security.getLogoutUrl() + "/*", security.getLogoutUrl()
120 )) : newArrayList();
121
122 final Collection<String> permitedRequests = newLinkedHashSet();
123
124 if (isNotBlank(security.getPermited())) {
125 permitedRequests.addAll(newArrayList(security.getPermited().split("[ ]*,[ ]*")));
126 }
127
128 permitedRequests.addAll(defaultPermited);
129
130 if (this.verifyCodeFilter != null) {
131 permitedRequests.add(this.verifyCodeFilter.getCodeUrl());
132 }
133
134 final Map<String, List<String>> grouped = permitedRequests.stream()
135 .map(expression -> {
136 final String[] fragments = expression.split(":");
137 return fragments.length == 1
138 ? newArrayList("", fragments[0]) : newArrayList(fragments[0].toUpperCase(), fragments[1]);
139 })
140 .collect(groupingBy(o -> o.get(0), mapping(o -> o.get(1), toList())));
141
142 return ImmutableMap.copyOf(grouped);
143 }
144 }