18
18
import jakarta .servlet .ServletException ;
19
19
import jakarta .servlet .http .HttpServletRequest ;
20
20
import jakarta .servlet .http .HttpServletResponse ;
21
-
22
- import java .io .IOException ;
23
- import java .security .Principal ;
24
- import java .util .List ;
25
- import java .util .Optional ;
26
-
27
21
import org .slf4j .Logger ;
28
22
import org .slf4j .LoggerFactory ;
29
23
import org .springframework .security .authentication .AnonymousAuthenticationToken ;
30
24
import org .springframework .security .config .annotation .web .builders .HttpSecurity ;
31
25
import org .springframework .security .config .annotation .web .configurers .LogoutConfigurer ;
32
26
import org .springframework .security .core .Authentication ;
27
+ import org .springframework .security .core .GrantedAuthority ;
33
28
import org .springframework .security .core .context .SecurityContext ;
34
29
import org .springframework .security .core .context .SecurityContextHolder ;
35
30
import org .springframework .security .web .authentication .logout .CompositeLogoutHandler ;
36
31
import org .springframework .security .web .authentication .logout .LogoutHandler ;
37
32
import org .springframework .security .web .authentication .logout .LogoutSuccessHandler ;
38
33
34
+ import java .io .IOException ;
35
+ import java .security .Principal ;
36
+ import java .util .Collection ;
37
+ import java .util .Collections ;
38
+ import java .util .List ;
39
+ import java .util .Optional ;
40
+ import java .util .Set ;
41
+ import java .util .stream .Collectors ;
42
+ import java .util .stream .Stream ;
43
+
39
44
import com .vaadin .flow .component .UI ;
40
45
import com .vaadin .flow .server .VaadinServletRequest ;
41
46
import com .vaadin .flow .server .VaadinServletResponse ;
@@ -63,6 +68,8 @@ public class AuthenticationContext {
63
68
64
69
private CompositeLogoutHandler logoutHandler ;
65
70
71
+ private VaadinRolePrefixHolder rolePrefixHolder ;
72
+
66
73
/**
67
74
* Gets an {@link Optional} with an instance of the current user if it has
68
75
* been authenticated, or empty if the user is not authenticated.
@@ -140,6 +147,198 @@ public void logout() {
140
147
});
141
148
}
142
149
150
+ /**
151
+ * Gets the authorities granted to the current authenticated user.
152
+ *
153
+ * @return an unmodifiable collection of {@link GrantedAuthority}s or an
154
+ * empty collection if there is no authenticated user.
155
+ */
156
+ public Collection <? extends GrantedAuthority > getGrantedAuthorities () {
157
+ return getAuthentication ().filter (Authentication ::isAuthenticated )
158
+ .map (Authentication ::getAuthorities )
159
+ .orElse (Collections .emptyList ());
160
+ }
161
+
162
+ private Stream <String > getGrantedAuthoritiesStream () {
163
+ return getGrantedAuthorities ().stream ()
164
+ .map (GrantedAuthority ::getAuthority );
165
+ }
166
+
167
+ /**
168
+ * Gets the roles granted to the current authenticated user.
169
+ *
170
+ * @return an unmodifiable collection of role names (without the role
171
+ * prefix) or an empty collection if there is no authenticated user.
172
+ */
173
+ public Collection <String > getGrantedRoles () {
174
+ return getGrantedRolesStream ().collect (Collectors .toSet ());
175
+ }
176
+
177
+ private Stream <String > getGrantedRolesStream () {
178
+ var rolePrefix = getRolePrefix ();
179
+ return getGrantedAuthoritiesStream ()
180
+ .filter (ga -> ga .startsWith (rolePrefix ))
181
+ .map (ga -> ga .substring (rolePrefix .length ()));
182
+ }
183
+
184
+ /**
185
+ * Checks whether the current authenticated user has the given role.
186
+ *
187
+ * @param role
188
+ * the role to check.
189
+ * @return {@literal true} if the user holds the given role, otherwise
190
+ * {@literal false}.
191
+ */
192
+ public boolean hasRole (String role ) {
193
+ return getGrantedRolesStream ().anyMatch (role ::equals );
194
+ }
195
+
196
+ /**
197
+ * Checks whether the current authenticated user has any of the given roles.
198
+ *
199
+ * @param roles
200
+ * a collection containing at least one role.
201
+ * @return {@literal true} if the user holds at least one of the given
202
+ * roles, otherwise {@literal false}.
203
+ * @throws IllegalArgumentException
204
+ * if the given collection is empty.
205
+ */
206
+ public boolean hasAnyRole (Collection <String > roles ) {
207
+ if (roles .isEmpty ()) {
208
+ throw new IllegalArgumentException (
209
+ "Must provide at least one role to check" );
210
+ }
211
+ return getGrantedRolesStream ().anyMatch (roles ::contains );
212
+ }
213
+
214
+ /**
215
+ * Checks whether the current authenticated user has any of the given roles.
216
+ *
217
+ * @param roles
218
+ * an array containing at least one role.
219
+ * @return {@literal true} if the user holds at least one of the given
220
+ * roles, otherwise {@literal false}.
221
+ * @throws IllegalArgumentException
222
+ * if the given array is empty.
223
+ */
224
+ public boolean hasAnyRole (String ... roles ) {
225
+ return hasAnyRole (Set .of (roles ));
226
+ }
227
+
228
+ /**
229
+ * Checks whether the current authenticated user has all the given roles.
230
+ *
231
+ * @param roles
232
+ * a collection containing at least one role.
233
+ * @return {@literal true} if the user holds all the given roles, otherwise
234
+ * {@literal false}.
235
+ * @throws IllegalArgumentException
236
+ * if the given collection is empty.
237
+ */
238
+ public boolean hasAllRoles (Collection <String > roles ) {
239
+ if (roles .isEmpty ()) {
240
+ throw new IllegalArgumentException (
241
+ "Must provide at least one role to check" );
242
+ }
243
+ return getGrantedRolesStream ().collect (Collectors .toSet ())
244
+ .containsAll (roles );
245
+ }
246
+
247
+ /**
248
+ * Checks whether the current authenticated user has all the given roles.
249
+ *
250
+ * @param roles
251
+ * an array containing at least one role.
252
+ * @return {@literal true} if the user holds all the given roles, otherwise
253
+ * {@literal false}.
254
+ * @throws IllegalArgumentException
255
+ * if the given array is empty.
256
+ */
257
+ public boolean hasAllRoles (String ... roles ) {
258
+ return hasAllRoles (Set .of (roles ));
259
+ }
260
+
261
+ /**
262
+ * Checks whether the current authenticated user has the given authority.
263
+ *
264
+ * @param authority
265
+ * the authority to check.
266
+ * @return {@literal true} if the user holds the given authority, otherwise
267
+ * {@literal false}.
268
+ */
269
+ public boolean hasAuthority (String authority ) {
270
+ return getGrantedAuthoritiesStream ().anyMatch (authority ::equals );
271
+ }
272
+
273
+ /**
274
+ * Checks whether the current authenticated user has any of the given
275
+ * authorities.
276
+ *
277
+ * @param authorities
278
+ * a collection containing at least one authority.
279
+ * @return {@literal true} if the user holds at least one of the given
280
+ * authorities, otherwise {@literal false}.
281
+ * @throws IllegalArgumentException
282
+ * if the given collection is empty.
283
+ */
284
+ public boolean hasAnyAuthority (Collection <String > authorities ) {
285
+ if (authorities .isEmpty ()) {
286
+ throw new IllegalArgumentException (
287
+ "Must provide at least one authority to check" );
288
+ }
289
+ return getGrantedAuthoritiesStream ().anyMatch (authorities ::contains );
290
+ }
291
+
292
+ /**
293
+ * Checks whether the current authenticated user has any of the given
294
+ * authorities.
295
+ *
296
+ * @param authorities
297
+ * an array containing at least one authority.
298
+ * @return {@literal true} if the user holds at least one of the given
299
+ * authorities, otherwise {@literal false}.
300
+ * @throws IllegalArgumentException
301
+ * if the given array is empty.
302
+ */
303
+ public boolean hasAnyAuthority (String ... authorities ) {
304
+ return hasAnyAuthority (Set .of (authorities ));
305
+ }
306
+
307
+ /**
308
+ * Checks whether the current authenticated user has all the given
309
+ * authorities.
310
+ *
311
+ * @param authorities
312
+ * a collection containing at least one authority.
313
+ * @return {@literal true} if the user holds all the given authorities,
314
+ * otherwise {@literal false}.
315
+ * @throws IllegalArgumentException
316
+ * if the given collection is empty.
317
+ */
318
+ public boolean hasAllAuthorities (Collection <String > authorities ) {
319
+ if (authorities .isEmpty ()) {
320
+ throw new IllegalArgumentException (
321
+ "Must provide at least one authority to check" );
322
+ }
323
+ return getGrantedAuthoritiesStream ().collect (Collectors .toSet ())
324
+ .containsAll (authorities );
325
+ }
326
+
327
+ /**
328
+ * Checks whether the current authenticated user has all the given
329
+ * authorities.
330
+ *
331
+ * @param authorities
332
+ * an array containing at least one authority.
333
+ * @return {@literal true} if the user holds all the given authorities,
334
+ * otherwise {@literal false}.
335
+ * @throws IllegalArgumentException
336
+ * if the given array is empty.
337
+ */
338
+ public boolean hasAllAuthorities (String ... authorities ) {
339
+ return hasAllAuthorities (Set .of (authorities ));
340
+ }
341
+
143
342
/**
144
343
* Sets component to handle logout process.
145
344
*
@@ -154,6 +353,18 @@ void setLogoutHandlers(LogoutSuccessHandler logoutSuccessHandler,
154
353
this .logoutHandler = new CompositeLogoutHandler (logoutHandlers );
155
354
}
156
355
356
+ /**
357
+ * Sets the role prefix holder to use when checking the current user's
358
+ * roles.
359
+ *
360
+ * @param rolePrefixHolder
361
+ * {@link VaadinRolePrefixHolder} instance, or {@literal null} to
362
+ * revert to the default {@code ROLE_} prefix.
363
+ */
364
+ void setRolePrefixHolder (VaadinRolePrefixHolder rolePrefixHolder ) {
365
+ this .rolePrefixHolder = rolePrefixHolder ;
366
+ }
367
+
157
368
private static Optional <Authentication > getAuthentication () {
158
369
return Optional .of (SecurityContextHolder .getContext ())
159
370
.map (SecurityContext ::getAuthentication )
@@ -170,6 +381,11 @@ CompositeLogoutHandler getLogoutHandler() {
170
381
return logoutHandler ;
171
382
}
172
383
384
+ private String getRolePrefix () {
385
+ return Optional .ofNullable (rolePrefixHolder )
386
+ .map (VaadinRolePrefixHolder ::getRolePrefix ).orElse ("ROLE_" );
387
+ }
388
+
173
389
/**
174
390
* Augments the given {@link AuthenticationContext} with Spring Security.
175
391
*
@@ -188,7 +404,6 @@ public static void applySecurityConfiguration(HttpSecurity httpSecurity,
188
404
.getConfigurer (LogoutConfigurer .class );
189
405
authCtx .setLogoutHandlers (logoutConfigurer .getLogoutSuccessHandler (),
190
406
logoutConfigurer .getLogoutHandlers ());
191
-
192
407
}
193
408
194
409
}
0 commit comments