1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.security.oauth2.config.annotation.web.configuration;
17
18 import java.util.Collections;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.servlet.http.HttpServletRequest;
24
25 import org.springframework.aop.framework.Advised;
26 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.context.ApplicationContext;
28 import org.springframework.context.annotation.Configuration;
29 import org.springframework.core.Ordered;
30 import org.springframework.security.authentication.AnonymousAuthenticationProvider;
31 import org.springframework.security.authentication.AuthenticationEventPublisher;
32 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
33 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
34 import org.springframework.security.config.http.SessionCreationPolicy;
35 import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
36 import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
37 import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
38 import org.springframework.security.oauth2.provider.token.TokenStore;
39 import org.springframework.security.web.util.matcher.RequestMatcher;
40 import org.springframework.util.ReflectionUtils;
41
42
43
44
45
46 @Configuration
47 public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered {
48
49 private int order = 3;
50
51 @Autowired(required = false)
52 private TokenStore tokenStore;
53
54 @Autowired(required = false)
55 private AuthenticationEventPublisher eventPublisher;
56
57 @Autowired(required = false)
58 private Map<String, ResourceServerTokenServices> tokenServices;
59
60 @Autowired
61 private ApplicationContext context;
62
63 private List<ResourceServerConfigurer> configurers = Collections.emptyList();
64
65 @Autowired(required = false)
66 private AuthorizationServerEndpointsConfiguration endpoints;
67
68 @Override
69 public int getOrder() {
70 return order;
71 }
72
73 public void setOrder(int order) {
74 this.order = order;
75 }
76
77
78
79
80 @Autowired(required = false)
81 public void setConfigurers(List<ResourceServerConfigurer> configurers) {
82 this.configurers = configurers;
83 }
84
85 private static class NotOAuthRequestMatcher implements RequestMatcher {
86
87 private FrameworkEndpointHandlerMapping mapping;
88
89 public NotOAuthRequestMatcher(FrameworkEndpointHandlerMapping mapping) {
90 this.mapping = mapping;
91 }
92
93 @Override
94 public boolean matches(HttpServletRequest request) {
95 String requestPath = getRequestPath(request);
96 for (String path : mapping.getPaths()) {
97 if (requestPath.startsWith(mapping.getPath(path))) {
98 return false;
99 }
100 }
101 return true;
102 }
103
104 private String getRequestPath(HttpServletRequest request) {
105 String url = request.getServletPath();
106
107 if (request.getPathInfo() != null) {
108 url += request.getPathInfo();
109 }
110
111 return url;
112 }
113
114 }
115
116 @Override
117 protected void configure(HttpSecurity http) throws Exception {
118 ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();
119 ResourceServerTokenServices services = resolveTokenServices();
120 if (services != null) {
121 resources.tokenServices(services);
122 }
123 else {
124 if (tokenStore != null) {
125 resources.tokenStore(tokenStore);
126 }
127 else if (endpoints != null) {
128 resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore());
129 }
130 }
131 if (eventPublisher != null) {
132 resources.eventPublisher(eventPublisher);
133 }
134 for (ResourceServerConfigurer configurer : configurers) {
135 configurer.configure(resources);
136 }
137
138 http.authenticationProvider(new AnonymousAuthenticationProvider("default"))
139
140
141 .exceptionHandling()
142 .accessDeniedHandler(resources.getAccessDeniedHandler()).and()
143 .sessionManagement()
144 .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
145 .csrf().disable();
146
147 http.apply(resources);
148 if (endpoints != null) {
149
150 http.requestMatcher(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping()));
151 }
152 for (ResourceServerConfigurer configurer : configurers) {
153
154 configurer.configure(http);
155 }
156 if (configurers.isEmpty()) {
157
158
159
160 http.authorizeRequests().anyRequest().authenticated();
161 }
162 }
163
164 private ResourceServerTokenServices resolveTokenServices() {
165 if (tokenServices == null || tokenServices.size() == 0) {
166 return null;
167 }
168 if (tokenServices.size() == 1) {
169 return tokenServices.values().iterator().next();
170 }
171 if (tokenServices.size() == 2) {
172
173 Iterator<ResourceServerTokenServices> iter = tokenServices.values().iterator();
174 ResourceServerTokenServices one = iter.next();
175 ResourceServerTokenServices two = iter.next();
176 if (elementsEqual(one, two)) {
177 return one;
178 }
179 }
180 return context.getBean(ResourceServerTokenServices.class);
181 }
182
183 private boolean elementsEqual(Object one, Object two) {
184
185 if (one == two) {
186 return true;
187 }
188 Object targetOne = findTarget(one);
189 Object targetTwo = findTarget(two);
190 return targetOne == targetTwo;
191 }
192
193 private Object findTarget(Object item) {
194 Object current = item;
195 while (current instanceof Advised) {
196 try {
197 current = ((Advised) current).getTargetSource().getTarget();
198 }
199 catch (Exception e) {
200 ReflectionUtils.rethrowRuntimeException(e);
201 }
202 }
203 return current;
204 }
205
206 }