1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.security.oauth.consumer.filter;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.springframework.beans.factory.InitializingBean;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.context.MessageSource;
24 import org.springframework.context.MessageSourceAware;
25 import org.springframework.context.support.MessageSourceAccessor;
26 import org.springframework.security.access.ConfigAttribute;
27 import org.springframework.security.authentication.InsufficientAuthenticationException;
28 import org.springframework.security.core.Authentication;
29 import org.springframework.security.core.SpringSecurityMessageSource;
30 import org.springframework.security.core.context.SecurityContextHolder;
31 import org.springframework.security.oauth.consumer.AccessTokenRequiredException;
32 import org.springframework.security.oauth.consumer.OAuthConsumerToken;
33 import org.springframework.security.oauth.consumer.OAuthSecurityContext;
34 import org.springframework.security.oauth.consumer.OAuthSecurityContextHolder;
35 import org.springframework.security.oauth.consumer.ProtectedResourceDetails;
36 import org.springframework.security.oauth.consumer.ProtectedResourceDetailsService;
37 import org.springframework.security.web.FilterInvocation;
38 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
39 import org.springframework.util.Assert;
40
41 import javax.servlet.*;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44 import java.io.IOException;
45 import java.util.Collection;
46 import java.util.Map;
47 import java.util.Set;
48 import java.util.TreeSet;
49
50
51
52
53
54
55
56
57
58
59 public class OAuthConsumerProcessingFilter implements Filter, InitializingBean, MessageSourceAware {
60
61 private static final Log LOG = LogFactory.getLog(OAuthConsumerProcessingFilter.class);
62
63 protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
64 private FilterInvocationSecurityMetadataSource objectDefinitionSource;
65 private boolean requireAuthenticated = true;
66
67 private ProtectedResourceDetailsService protectedResourceDetailsService;
68
69 public void afterPropertiesSet() throws Exception {
70 Assert.notNull(protectedResourceDetailsService, "A protected resource details service is required.");
71 Assert.notNull(objectDefinitionSource, "The object definition source must be configured.");
72 }
73
74 public void init(FilterConfig ignored) throws ServletException {
75 }
76
77 public void destroy() {
78 }
79
80 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
81 HttpServletRequest request = (HttpServletRequest) servletRequest;
82 HttpServletResponse response = (HttpServletResponse) servletResponse;
83
84 Set<String> accessTokenDeps = getAccessTokenDependencies(request, response, chain);
85 if (!accessTokenDeps.isEmpty()) {
86 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
87 if (isRequireAuthenticated() && !authentication.isAuthenticated()) {
88 throw new InsufficientAuthenticationException("An authenticated principal must be present.");
89 }
90
91 OAuthSecurityContext context = OAuthSecurityContextHolder.getContext();
92 if (context == null) {
93 throw new IllegalStateException("No OAuth security context has been established. Unable to access resources.");
94 }
95
96 Map<String, OAuthConsumerToken> accessTokens = context.getAccessTokens();
97
98 for (String dependency : accessTokenDeps) {
99 if (!accessTokens.containsKey(dependency)) {
100 throw new AccessTokenRequiredException(getProtectedResourceDetailsService().loadProtectedResourceDetailsById(dependency));
101 }
102 }
103
104 chain.doFilter(request, response);
105 }
106 else {
107 if (LOG.isDebugEnabled()) {
108 LOG.debug("No access token dependencies for request.");
109 }
110 chain.doFilter(servletRequest, servletResponse);
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 protected Set<String> getAccessTokenDependencies(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
124 Set<String> deps = new TreeSet<String>();
125
126 if (getObjectDefinitionSource() != null) {
127 FilterInvocation invocation = new FilterInvocation(request, response, filterChain);
128 Collection<ConfigAttribute> attributes = getObjectDefinitionSource().getAttributes(invocation);
129 if (attributes != null) {
130 for (ConfigAttribute attribute : attributes) {
131 deps.add(attribute.getAttribute());
132 }
133 }
134 }
135 return deps;
136 }
137
138
139
140
141
142
143 public ProtectedResourceDetailsService getProtectedResourceDetailsService() {
144 return protectedResourceDetailsService;
145 }
146
147
148
149
150
151
152
153 @Autowired
154 public void setProtectedResourceDetailsService(ProtectedResourceDetailsService protectedResourceDetailsService) {
155 this.protectedResourceDetailsService = protectedResourceDetailsService;
156 }
157
158
159
160
161
162
163 public FilterInvocationSecurityMetadataSource getObjectDefinitionSource() {
164 return objectDefinitionSource;
165 }
166
167
168
169
170
171
172 public void setObjectDefinitionSource(FilterInvocationSecurityMetadataSource objectDefinitionSource) {
173 this.objectDefinitionSource = objectDefinitionSource;
174 }
175
176
177
178
179
180
181 public void setMessageSource(MessageSource messageSource) {
182 this.messages = new MessageSourceAccessor(messageSource);
183 }
184
185
186
187
188
189
190 public boolean isRequireAuthenticated() {
191 return requireAuthenticated;
192 }
193
194
195
196
197
198
199 public void setRequireAuthenticated(boolean requireAuthenticated) {
200 this.requireAuthenticated = requireAuthenticated;
201 }
202
203 }