-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial Native section to reference docs
Also add the first subsection approaching how to handle method security in a native image Closes gh-12029 Closes gh-13226
- Loading branch information
1 parent
55c374d
commit f9b6d17
Showing
3 changed files
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
= GraalVM Native Image Support | ||
|
||
Spring Boot 3.0 provides https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.introducing-graalvm-native-images[support for generating native images with GraalVM]. | ||
Spring Security integrates with that support and provides its features ready for native images. | ||
|
||
However, as mentioned in the https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.introducing-graalvm-native-images.understanding-aot-processing.hint-file-generation[Spring Boot documentation], there are some cases where we need to provide hints to be used by GraalVM. | ||
|
||
This section aims to provide guidance in some Spring Security features that likely need to have additional hints provided by the application. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
[[native-image-method-security]] | ||
= Method Security in GraalVM Native Image | ||
|
||
Although xref:servlet/authorization/method-security.adoc[Method Security] is supported in GraalVM Native Image, there are some use cases that need additional hints provided by the application. | ||
|
||
== Using `@PreAuthorize` and `@PostAuthorize` Annotations | ||
|
||
Using `@PreAuthorize` and `@PostAuthorize` annotations require additional hints if you have a custom implementation of `UserDetails` or `Authentication` classes. | ||
|
||
Let's take an example where you have a custom implementation of `UserDetails` class as follows and that implementation is returned by your `UserDetailsService`: | ||
|
||
==== | ||
.Custom Implementation of UserDetails | ||
[source,java] | ||
---- | ||
public class CustomUserDetails implements UserDetails { | ||
private final String username; | ||
private final String password; | ||
private final Collection<? extends GrantedAuthority> authorities; | ||
public boolean isAdmin() { | ||
return this.authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN")); | ||
} | ||
// constructors, getters and setters | ||
} | ||
---- | ||
==== | ||
|
||
And you want to use the `isAdmin()` method inside a `@PreAuthorize` annotation as follows: | ||
|
||
==== | ||
.Using isAdmin() to secure a method | ||
[source,java] | ||
---- | ||
@PreAuthorize("principal?.isAdmin()") | ||
public String hello() { | ||
return "Hello!"; | ||
} | ||
---- | ||
==== | ||
|
||
[NOTE] | ||
==== | ||
Remember that you need to xref:servlet/authorization/method-security.adoc#jc-enable-method-security[add `@EnableMethodSecurity` annotation] to your configuration class to enable method security annotations. | ||
==== | ||
|
||
If you https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.developing-your-first-application[run the native image] of your application with the above configuration, you will get an error similar to the following when trying to invoke the `hello()` method: | ||
|
||
[source] | ||
---- | ||
failed: java.lang.IllegalArgumentException: Failed to evaluate expression 'principal?.isAdmin()' with root cause | ||
org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method isAdmin() cannot be found on type com.mypackage.CustomUserDetails | ||
---- | ||
|
||
Which means that the `isAdmin()` method cannot be found on the `CustomUserDetails` class. | ||
This is because Spring Security uses reflection to invoke the `isAdmin()` method and GraalVM Native Image does not support reflection by default. | ||
|
||
To fix this issue, you need to give hints to GraalVM Native Image to allow reflection on the `CustomUserDetails#isAdmin()` method. | ||
We can do that by providing a https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.advanced.custom-hints[custom hint]. | ||
In this example we are going to use {spring-framework-reference-url}core.html#core.aot.hints.register-reflection-for-binding[the `@RegisterReflectionForBinding` annotation]. | ||
|
||
[NOTE] | ||
==== | ||
You might need to register all your classes that you want to use in your `@PreAuthorize` and `@PostAuthorize` annotations. | ||
==== | ||
|
||
==== | ||
.Using @RegisterReflectionForBinding | ||
[source,java] | ||
---- | ||
@Configuration | ||
@RegisterReflectionForBinding(CustomUserDetails.class) | ||
public class MyConfiguration { | ||
//... | ||
} | ||
---- | ||
==== | ||
|
||
And that's it, now you can run the native image of your application and it should work as expected. |