1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.taglibs.authz;
17
18 import org.acegisecurity.Authentication;
19 import org.acegisecurity.GrantedAuthority;
20 import org.acegisecurity.GrantedAuthorityImpl;
21 import org.acegisecurity.context.SecurityContextHolder;
22
23 import org.springframework.util.StringUtils;
24
25 import org.springframework.web.util.ExpressionEvaluationUtils;
26
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.Set;
33
34 import javax.servlet.jsp.JspException;
35 import javax.servlet.jsp.tagext.Tag;
36 import javax.servlet.jsp.tagext.TagSupport;
37
38
39 /***
40 * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's
41 * body through if some authorizations are granted to the request's principal.
42 *
43 * @author Francois Beausoleil
44 * @version $Id: AuthorizeTag.java,v 1.13 2005/11/17 00:56:29 benalex Exp $
45 */
46 public class AuthorizeTag extends TagSupport {
47
48
49 private String ifAllGranted = "";
50 private String ifAnyGranted = "";
51 private String ifNotGranted = "";
52
53
54
55 public void setIfAllGranted(String ifAllGranted) throws JspException {
56 this.ifAllGranted = ifAllGranted;
57 }
58
59 public String getIfAllGranted() {
60 return ifAllGranted;
61 }
62
63 public void setIfAnyGranted(String ifAnyGranted) throws JspException {
64 this.ifAnyGranted = ifAnyGranted;
65 }
66
67 public String getIfAnyGranted() {
68 return ifAnyGranted;
69 }
70
71 public void setIfNotGranted(String ifNotGranted) throws JspException {
72 this.ifNotGranted = ifNotGranted;
73 }
74
75 public String getIfNotGranted() {
76 return ifNotGranted;
77 }
78
79 public int doStartTag() throws JspException {
80 if (((null == ifAllGranted) || "".equals(ifAllGranted))
81 && ((null == ifAnyGranted) || "".equals(ifAnyGranted))
82 && ((null == ifNotGranted) || "".equals(ifNotGranted))) {
83 return Tag.SKIP_BODY;
84 }
85
86 final Collection granted = getPrincipalAuthorities();
87
88 final String evaledIfNotGranted = ExpressionEvaluationUtils
89 .evaluateString("ifNotGranted", ifNotGranted, pageContext);
90
91 if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) {
92 Set grantedCopy = retainAll(granted,
93 parseAuthoritiesString(evaledIfNotGranted));
94
95 if (!grantedCopy.isEmpty()) {
96 return Tag.SKIP_BODY;
97 }
98 }
99
100 final String evaledIfAllGranted = ExpressionEvaluationUtils
101 .evaluateString("ifAllGranted", ifAllGranted, pageContext);
102
103 if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) {
104 if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) {
105 return Tag.SKIP_BODY;
106 }
107 }
108
109 final String evaledIfAnyGranted = ExpressionEvaluationUtils
110 .evaluateString("ifAnyGranted", ifAnyGranted, pageContext);
111
112 if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) {
113 Set grantedCopy = retainAll(granted,
114 parseAuthoritiesString(evaledIfAnyGranted));
115
116 if (grantedCopy.isEmpty()) {
117 return Tag.SKIP_BODY;
118 }
119 }
120
121 return Tag.EVAL_BODY_INCLUDE;
122 }
123
124 private Collection getPrincipalAuthorities() {
125 Authentication currentUser = SecurityContextHolder.getContext()
126 .getAuthentication();
127
128 if (null == currentUser) {
129 return Collections.EMPTY_LIST;
130 }
131
132 if ((null == currentUser.getAuthorities())
133 || (currentUser.getAuthorities().length < 1)) {
134 return Collections.EMPTY_LIST;
135 }
136
137 Collection granted = Arrays.asList(currentUser.getAuthorities());
138
139 return granted;
140 }
141
142 private Set authoritiesToRoles(Collection c) {
143 Set target = new HashSet();
144
145 for (Iterator iterator = c.iterator(); iterator.hasNext();) {
146 GrantedAuthority authority = (GrantedAuthority) iterator.next();
147
148 if (null == authority.getAuthority()) {
149 throw new IllegalArgumentException(
150 "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process "
151 + authority.toString());
152 }
153
154 target.add(authority.getAuthority());
155 }
156
157 return target;
158 }
159
160 private Set parseAuthoritiesString(String authorizationsString) {
161 final Set requiredAuthorities = new HashSet();
162 final String[] authorities = StringUtils
163 .commaDelimitedListToStringArray(authorizationsString);
164
165 for (int i = 0; i < authorities.length; i++) {
166 String authority = authorities[i];
167
168
169
170 String role = StringUtils.replace(authority, " ", "");
171 role = StringUtils.replace(role, "\t", "");
172 role = StringUtils.replace(role, "\r", "");
173 role = StringUtils.replace(role, "\n", "");
174 role = StringUtils.replace(role, "\f", "");
175
176 requiredAuthorities.add(new GrantedAuthorityImpl(role));
177 }
178
179 return requiredAuthorities;
180 }
181
182 /***
183 * Find the common authorities between the current authentication's {@link
184 * GrantedAuthority} and the ones that have been specified in the tag's
185 * ifAny, ifNot or ifAllGranted attributes.
186 *
187 * <p>
188 * We need to manually iterate over both collections, because the granted
189 * authorities might not implement {@link Object#equals(Object)} and
190 * {@link Object#hashCode()} in the same way as {@link
191 * GrantedAuthorityImpl}, thereby invalidating {@link
192 * Collection#retainAll(java.util.Collection)} results.
193 * </p>
194 *
195 * <p>
196 * <strong>CAVEAT</strong>: This method <strong>will not</strong> work if
197 * the granted authorities returns a <code>null</code> string as the
198 * return value of {@link
199 * org.acegisecurity.GrantedAuthority#getAuthority()}.
200 * </p>
201 *
202 * <p>
203 * Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Acegi Security
204 * System for Spring forums.
205 * </p>
206 *
207 * @param granted The authorities granted by the authentication. May be any
208 * implementation of {@link GrantedAuthority} that does
209 * <strong>not</strong> return <code>null</code> from {@link
210 * org.acegisecurity.GrantedAuthority#getAuthority()}.
211 * @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have
212 * been built using ifAny, ifAll or ifNotGranted.
213 *
214 * @return A set containing only the common authorities between
215 * <var>granted</var> and <var>required</var>.
216 *
217 * @see <a
218 * href="http://forum.springframework.org/viewtopic.php?t=3367">authz:authorize
219 * ifNotGranted not behaving as expected</a>
220 */
221 private Set retainAll(final Collection granted, final Set required) {
222 Set grantedRoles = authoritiesToRoles(granted);
223 Set requiredRoles = authoritiesToRoles(required);
224 grantedRoles.retainAll(requiredRoles);
225
226 return rolesToAuthorities(grantedRoles, granted);
227 }
228
229 private Set rolesToAuthorities(Set grantedRoles, Collection granted) {
230 Set target = new HashSet();
231
232 for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) {
233 String role = (String) iterator.next();
234
235 for (Iterator grantedIterator = granted.iterator();
236 grantedIterator.hasNext();) {
237 GrantedAuthority authority = (GrantedAuthority) grantedIterator
238 .next();
239
240 if (authority.getAuthority().equals(role)) {
241 target.add(authority);
242
243 break;
244 }
245 }
246 }
247
248 return target;
249 }
250 }