parent
134a0a7f96
commit
988b54ec3d
|
@ -121,7 +121,7 @@ It is normal and shouldn't be anything to worry about.
|
|||
[[appendix-faq-cached-secure-page]]
|
||||
==== Why can I still see a secured page even after I've logged out of my application?
|
||||
|
||||
The most common reason for this is that your browser has cached the page and you are seeing a copy which is being retrieved from the browsers cache. Verify this by checking whether the browser is actually sending the request (check your server access logs, the debug log or use a suitable browser debugging plugin such as "Tamper Data" for Firefox). This has nothing to do with Spring Security and you should configure your application or server to set the appropriate`Cache-Control` response headers. Note that SSL requests are never cached.
|
||||
The most common reason for this is that your browser has cached the page and you are seeing a copy which is being retrieved from the browsers cache. Verify this by checking whether the browser is actually sending the request (check your server access logs, the debug log or use a suitable browser debugging plugin such as "Tamper Data" for Firefox). This has nothing to do with Spring Security and you should configure your application or server to set the appropriate `Cache-Control` response headers. Note that SSL requests are never cached.
|
||||
|
||||
|
||||
[[auth-exception-credentials-not-found]]
|
||||
|
@ -214,7 +214,7 @@ This usually means that the user's application is creating a session somewhere,
|
|||
|
||||
If you are having trouble working out where a session is being created, you can add some debugging code to track down the location(s). One way to do this would be to add a `javax.servlet.http.HttpSessionListener` to your application, which calls `Thread.dumpStack()` in the `sessionCreated` method.
|
||||
|
||||
[[forbidden-csrf]]
|
||||
[[appendix-faq-forbidden-csrf]]
|
||||
==== I get a 403 Forbidden when performing a POST
|
||||
|
||||
If an HTTP 403 Forbidden is returned for HTTP POST, but works for HTTP GET then the issue is most likely related to http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf[CSRF]. Either provide the CSRF Token or disable CSRF protection (not recommended).
|
||||
|
@ -308,7 +308,7 @@ The other required jars should be pulled in transitively.
|
|||
[[appendix-faq-what-is-userdetailservice]]
|
||||
==== What is a UserDetailsService and do I need one?
|
||||
|
||||
`UserDetailsService` is a DAO interface for loading data that is specific to a user account. It has no other function other to load that data for use by other components within the framework. It is not responsible for authenticating the user. Authenticating a user with a username/password combination is most commonly performed by the`DaoAuthenticationProvider`, which is injected with a `UserDetailsService` to allow it to load the password (and other data) for a user in order to compare it with the submitted value. Note that if you are using LDAP, <<appendix-faq-ldap-authentication,this approach may not work>>.
|
||||
`UserDetailsService` is a DAO interface for loading data that is specific to a user account. It has no other function other to load that data for use by other components within the framework. It is not responsible for authenticating the user. Authenticating a user with a username/password combination is most commonly performed by the `DaoAuthenticationProvider`, which is injected with a `UserDetailsService` to allow it to load the password (and other data) for a user in order to compare it with the submitted value. Note that if you are using LDAP, <<appendix-faq-ldap-authentication,this approach may not work>>.
|
||||
|
||||
If you want to customize the authentication process then you should implement `AuthenticationProvider` yourself. See this http://blog.springsource.com/2010/08/02/spring-security-in-google-app-engine/[ blog article] for an example integrating Spring Security authentication with Google App Engine.
|
||||
|
||||
|
@ -330,9 +330,9 @@ If you want to customize the authentication process then you should implement `A
|
|||
|
||||
This question comes up repeatedly in the Spring Security forum so you will find more information there by searching the archives (or through google).
|
||||
|
||||
The submitted login information is processed by an instance of `UsernamePasswordAuthenticationFilter`. You will need to customize this class to handle the extra data field(s). One option is to use your own customized authentication token class (rather than the standard`UsernamePasswordAuthenticationToken`), another is simply to concatenate the extra fields with the username (for example, using a ":" as the separator) and pass them in the username property of `UsernamePasswordAuthenticationToken`.
|
||||
The submitted login information is processed by an instance of `UsernamePasswordAuthenticationFilter`. You will need to customize this class to handle the extra data field(s). One option is to use your own customized authentication token class (rather than the standard `UsernamePasswordAuthenticationToken`), another is simply to concatenate the extra fields with the username (for example, using a ":" as the separator) and pass them in the username property of `UsernamePasswordAuthenticationToken`.
|
||||
|
||||
You will also need to customize the actual authentication process. If you are using a custom authentication token class, for example, you will have to write an `AuthenticationProvider` to handle it (or extend the standard`DaoAuthenticationProvider`). If you have concatenated the fields, you can implement your own`UserDetailsService` which splits them up and loads the appropriate user data for authentication.
|
||||
You will also need to customize the actual authentication process. If you are using a custom authentication token class, for example, you will have to write an `AuthenticationProvider` to handle it (or extend the standard `DaoAuthenticationProvider`). If you have concatenated the fields, you can implement your own `UserDetailsService` which splits them up and loads the appropriate user data for authentication.
|
||||
|
||||
[[appendix-faq-matching-url-fragments]]
|
||||
==== How do I apply different intercept-url constraints where only the fragment value of the requested URLs differs (e.g./foo#bar and /foo#blah?
|
||||
|
@ -342,15 +342,15 @@ You can't do this, since the fragment is not transmitted from the browser to the
|
|||
[[appendix-faq-request-details-in-user-service]]
|
||||
==== How do I access the user's IP Address (or other web-request data) in a UserDetailsService?
|
||||
|
||||
Obviously you can't (without resorting to something like thread-local variables) since the only information supplied to the interface is the username. Instead of implementing `UserDetailsService`, you should implement `AuthenticationProvider` directly and extract the information from the supplied`Authentication` token.
|
||||
Obviously you can't (without resorting to something like thread-local variables) since the only information supplied to the interface is the username. Instead of implementing `UserDetailsService`, you should implement `AuthenticationProvider` directly and extract the information from the supplied `Authentication` token.
|
||||
|
||||
In a standard web setup, the `getDetails()` method on the `Authentication` object will return an instance of `WebAuthenticationDetails`. If you need additional information, you can inject a custom`AuthenticationDetailsSource` into the authentication filter you are using. If you are using the namespace, for example with the `<form-login>` element, then you should remove this element and replace it with a`<custom-filter>` declaration pointing to an explicitly configured`UsernamePasswordAuthenticationFilter`.
|
||||
In a standard web setup, the `getDetails()` method on the `Authentication` object will return an instance of `WebAuthenticationDetails`. If you need additional information, you can inject a custom `AuthenticationDetailsSource` into the authentication filter you are using. If you are using the namespace, for example with the `<form-login>` element, then you should remove this element and replace it with a `<custom-filter>` declaration pointing to an explicitly configured `UsernamePasswordAuthenticationFilter`.
|
||||
|
||||
|
||||
[[appendix-faq-access-session-from-user-service]]
|
||||
==== How do I access the HttpSession from a UserDetailsService?
|
||||
|
||||
You can't, since the `UserDetailsService` has no awareness of the servlet API. If you want to store custom user data, then you should customize the`UserDetails` object which is returned. This can then be accessed at any point, via the thread-local`SecurityContextHolder`. A call to `SecurityContextHolder.getContext().getAuthentication().getPrincipal()` will return this custom object.
|
||||
You can't, since the `UserDetailsService` has no awareness of the servlet API. If you want to store custom user data, then you should customize the `UserDetails` object which is returned. This can then be accessed at any point, via the thread-local `SecurityContextHolder`. A call to `SecurityContextHolder.getContext().getAuthentication().getPrincipal()` will return this custom object.
|
||||
|
||||
If you really need to access the session, then it must be done by customizing the web tier.
|
||||
|
||||
|
@ -368,9 +368,9 @@ People often ask about how to store the mapping between secured URLs and securit
|
|||
|
||||
The first thing you should ask yourself is if you really need to do this. If an application requires securing, then it also requires that the security be tested thoroughly based on a defined policy. It may require auditing and acceptance testing before being rolled out into a production environment. A security-conscious organization should be aware that the benefits of their diligent testing process could be wiped out instantly by allowing the security settings to be modified at runtime by changing a row or two in a configuration database. If you have taken this into account (perhaps using multiple layers of security within your application) then Spring Security allows you to fully customize the source of security metadata. You can make it fully dynamic if you choose.
|
||||
|
||||
Both method and web security are protected by subclasses of `AbstractSecurityInterceptor` which is configured with a `SecurityMetadataSource` from which it obtains the metadata for a particular method or filter invocation. For web security, the interceptor class is `FilterSecurityInterceptor` and it uses the marker interface`FilterInvocationSecurityMetadataSource`. The "secured object" type it operates on is a `FilterInvocation`. The default implementation which is used (both in the namespace `<http>` and when configuring the interceptor explicitly, stores the list of URL patterns and their corresponding list of "configuration attributes" (instances of `ConfigAttribute`) in an in-memory map.
|
||||
Both method and web security are protected by subclasses of `AbstractSecurityInterceptor` which is configured with a `SecurityMetadataSource` from which it obtains the metadata for a particular method or filter invocation. For web security, the interceptor class is `FilterSecurityInterceptor` and it uses the marker interface `FilterInvocationSecurityMetadataSource`. The "secured object" type it operates on is a `FilterInvocation`. The default implementation which is used (both in the namespace `<http>` and when configuring the interceptor explicitly, stores the list of URL patterns and their corresponding list of "configuration attributes" (instances of `ConfigAttribute`) in an in-memory map.
|
||||
|
||||
To load the data from an alternative source, you must be using an explicitly declared security filter chain (typically Spring Security's`FilterChainProxy`) in order to customize the `FilterSecurityInterceptor` bean. You can't use the namespace. You would then implement`FilterInvocationSecurityMetadataSource` to load the data as you please for a particular`FilterInvocation` footnote:[The `FilterInvocation` object contains the `HttpServletRequest`, so you can obtain the URL or any other relevant information on which to base your decision on what the list of returned attributes will contain.]. A very basic outline would look something like this:
|
||||
To load the data from an alternative source, you must be using an explicitly declared security filter chain (typically Spring Security's `FilterChainProxy`) in order to customize the `FilterSecurityInterceptor` bean. You can't use the namespace. You would then implement `FilterInvocationSecurityMetadataSource` to load the data as you please for a particular `FilterInvocation` footnote:[The `FilterInvocation` object contains the `HttpServletRequest`, so you can obtain the URL or any other relevant information on which to base your decision on what the list of returned attributes will contain.]. A very basic outline would look something like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -406,7 +406,7 @@ For more information, look at the code for `DefaultFilterInvocationSecurityMetad
|
|||
[[appendix-faq-ldap-authorities]]
|
||||
==== How do I authenticate against LDAP but load user roles from a database?
|
||||
|
||||
The `LdapAuthenticationProvider` bean (which handles normal LDAP authentication in Spring Security) is configured with two separate strategy interfaces, one which performs the authenticatation and one which loads the user authorities, called`LdapAuthenticator` and `LdapAuthoritiesPopulator` respectively. The `DefaultLdapAuthoritiesPopulator` loads the user authorities from the LDAP directory and has various configuration parameters to allow you to specify how these should be retrieved.
|
||||
The `LdapAuthenticationProvider` bean (which handles normal LDAP authentication in Spring Security) is configured with two separate strategy interfaces, one which performs the authentication and one which loads the user authorities, called `LdapAuthenticator` and `LdapAuthoritiesPopulator` respectively. The `DefaultLdapAuthoritiesPopulator` loads the user authorities from the LDAP directory and has various configuration parameters to allow you to specify how these should be retrieved.
|
||||
|
||||
To use JDBC instead, you can implement the interface yourself, using whatever SQL is appropriate for your schema:
|
||||
|
||||
|
@ -440,9 +440,9 @@ You would then add a bean of this type to your application context and inject it
|
|||
[[appendix-faq-namespace-post-processor]]
|
||||
==== I want to modify the property of a bean that is created by the namespace, but there is nothing in the schema to support it. What can I do short of abandoning namespace use?
|
||||
|
||||
The namespace functionality is intentionally limited, so it doesn't cover everything that you can do with plain beans. If you want to do something simple, like modify a bean, or inject a different dependency, you can do this by adding a`BeanPostProcessor` to your configuration. More information can be found in the http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-factory-extension-bpp[Spring Reference Manual]. In order to do this, you need to know a bit about which beans are created, so you should also read the blog article in the above question on <<appendix-faq-namespace-to-bean-mapping,how the namespace maps to Spring beans>>.
|
||||
The namespace functionality is intentionally limited, so it doesn't cover everything that you can do with plain beans. If you want to do something simple, like modify a bean, or inject a different dependency, you can do this by adding a `BeanPostProcessor` to your configuration. More information can be found in the http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-factory-extension-bpp[Spring Reference Manual]. In order to do this, you need to know a bit about which beans are created, so you should also read the blog article in the above question on <<appendix-faq-namespace-to-bean-mapping,how the namespace maps to Spring beans>>.
|
||||
|
||||
Normally, you would add the functionality you require to the `postProcessBeforeInitialization` method of`BeanPostProcessor`. Let's say that you want to customize the`AuthenticationDetailsSource` used by the `UsernamePasswordAuthenticationFilter`, (created by the `form-login` element). You want to extract a particular header called `CUSTOM_HEADER`from the request and make use of it while authenticating the user. The processor class would look like this:
|
||||
Normally, you would add the functionality you require to the `postProcessBeforeInitialization` method of `BeanPostProcessor`. Let's say that you want to customize the `AuthenticationDetailsSource` used by the `UsernamePasswordAuthenticationFilter`, (created by the `form-login` element). You want to extract a particular header called `CUSTOM_HEADER` from the request and make use of it while authenticating the user. The processor class would look like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
|
|
@ -14,7 +14,7 @@ public class HelloMessageService implements MessageService {
|
|||
@PreAuthorize("authenticated")
|
||||
public String getMessage() {
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
.getAuthentication();
|
||||
return "Hello " + authentication;
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ mvc
|
|||
.perform(get("/").with(securityContext(securityContext)))
|
||||
----
|
||||
|
||||
We can also ensure to run as a specific user for every request by using `MockMvcBuilders`'s default request.
|
||||
We can also ensure to run as a specific user for every request by using ``MockMvcBuilders``'s default request.
|
||||
For example, the following will run as a user (which does not need to exist) with the username "admin", the password "password", and the role "ROLE_ADMIN":
|
||||
|
||||
[source,java]
|
||||
|
@ -525,8 +525,8 @@ For example, the following will run the test with the user with username "user",
|
|||
@WithMockUser
|
||||
public void requestProtectedUrlWithUser() throws Exception {
|
||||
mvc
|
||||
.perform(get("/"))
|
||||
...
|
||||
.perform(get("/"))
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
|
@ -538,8 +538,8 @@ Alternatively, the following will run the test with the user with username "user
|
|||
@WithMockUser(roles="ADMIN")
|
||||
public void requestProtectedUrlWithUser() throws Exception {
|
||||
mvc
|
||||
.perform(get("/"))
|
||||
...
|
||||
.perform(get("/"))
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
|
|
|
@ -2025,7 +2025,7 @@ The object returned by the call to `getContext()` is an instance of the `Securit
|
|||
|
||||
[[tech-userdetailsservice]]
|
||||
==== The UserDetailsService
|
||||
Another item to note from the above code fragment is that you can obtain a principal from the `Authentication` object. The principal is just an `Object`. Most of the time this can be cast into a `UserDetails` object. `UserDetails` is a core interface in Spring Security. It represents a principal, but in an extensible and application-specific way. Think of `UserDetails` as the adapter between your own user database and what Spring Security needs inside the `SecurityContextHolder`. Being a representation of something from your own user database, quite often you will cast the `UserDetails` to the original object that your application provided, so you can call business-specific methods (like`getEmail()`, `getEmployeeNumber()` and so on).
|
||||
Another item to note from the above code fragment is that you can obtain a principal from the `Authentication` object. The principal is just an `Object`. Most of the time this can be cast into a `UserDetails` object. `UserDetails` is a core interface in Spring Security. It represents a principal, but in an extensible and application-specific way. Think of `UserDetails` as the adapter between your own user database and what Spring Security needs inside the `SecurityContextHolder`. Being a representation of something from your own user database, quite often you will cast the `UserDetails` to the original object that your application provided, so you can call business-specific methods (like `getEmail()`, `getEmployeeNumber()` and so on).
|
||||
|
||||
By now you're probably wondering, so when do I provide a `UserDetails` object? How do I do that? I thought you said this thing was declarative and I didn't need to write any Java code - what gives? The short answer is that there is a special interface called `UserDetailsService`. The only method on this interface accepts a `String`-based username argument and returns a `UserDetails`:
|
||||
|
||||
|
@ -2261,7 +2261,7 @@ Each supported secure object type has its own interceptor class, which is a subc
|
|||
|
||||
[[tech-intro-config-attributes]]
|
||||
===== What are Configuration Attributes?
|
||||
A "configuration attribute" can be thought of as a String that has special meaning to the classes used by `AbstractSecurityInterceptor`. They are represented by the interface `ConfigAttribute` within the framework. They may be simple role names or have more complex meaning, depending on the how sophisticated the `AccessDecisionManager` implementation is. The `AbstractSecurityInterceptor` is configured with a `SecurityMetadataSource` which it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user. Configuration attributes will be entered as annotations on secured methods or as access attributes on secured URLs. For example, when we saw something like `<intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B'/>` in the namespace introduction, this is saying that the configuration attributes `ROLE_A` and `ROLE_B` apply to web requests matching the given pattern. In practice, with the default `AccessDecisionManager` configuration, this means that anyone who has a `GrantedAuthority` matching either of these two attributes will be allowed access. Strictly speaking though, they are just attributes and the interpretation is dependent on the `AccessDecisionManager` implementation. The use of the prefix `ROLE_` is a marker to indicate that these attributes are roles and should be consumed by Spring Security's`RoleVoter`. This is only relevant when a voter-based `AccessDecisionManager` is in use. We'll see how the `AccessDecisionManager` is implemented in the <<authz-arch,authorization chapter>>.
|
||||
A "configuration attribute" can be thought of as a String that has special meaning to the classes used by `AbstractSecurityInterceptor`. They are represented by the interface `ConfigAttribute` within the framework. They may be simple role names or have more complex meaning, depending on the how sophisticated the `AccessDecisionManager` implementation is. The `AbstractSecurityInterceptor` is configured with a `SecurityMetadataSource` which it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user. Configuration attributes will be entered as annotations on secured methods or as access attributes on secured URLs. For example, when we saw something like `<intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B'/>` in the namespace introduction, this is saying that the configuration attributes `ROLE_A` and `ROLE_B` apply to web requests matching the given pattern. In practice, with the default `AccessDecisionManager` configuration, this means that anyone who has a `GrantedAuthority` matching either of these two attributes will be allowed access. Strictly speaking though, they are just attributes and the interpretation is dependent on the `AccessDecisionManager` implementation. The use of the prefix `ROLE_` is a marker to indicate that these attributes are roles and should be consumed by Spring Security's `RoleVoter`. This is only relevant when a voter-based `AccessDecisionManager` is in use. We'll see how the `AccessDecisionManager` is implemented in the <<authz-arch,authorization chapter>>.
|
||||
|
||||
|
||||
===== RunAsManager
|
||||
|
@ -2287,7 +2287,7 @@ Spring Security supports localization of exception messages that end users are l
|
|||
|
||||
All exception messages can be localized, including messages related to authentication failures and access being denied (authorization failures). Exceptions and logging messages that are focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) are not localized and instead are hard-coded in English within Spring Security's code.
|
||||
|
||||
Shipping in the `spring-security-core-xx.jar` you will find an `org.springframework.security` package that in turn contains a `messages.properties` file, as well as localized versions for some common languages. This should be referred to by your`ApplicationContext`, as Spring Security classes implement Spring's `MessageSourceAware` interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below:
|
||||
Shipping in the `spring-security-core-xx.jar` you will find an `org.springframework.security` package that in turn contains a `messages.properties` file, as well as localized versions for some common languages. This should be referred to by your `ApplicationContext`, as Spring Security classes implement Spring's `MessageSourceAware` interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -2301,7 +2301,7 @@ The `messages.properties` is named in accordance with standard resource bundles
|
|||
|
||||
If you wish to customize the `messages.properties` file, or support other languages, you should copy the file, rename it accordingly, and register it inside the above bean definition. There are not a large number of message keys inside this file, so localization should not be considered a major initiative. If you do perform localization of this file, please consider sharing your work with the community by logging a JIRA task and attaching your appropriately-named localized version of `messages.properties`.
|
||||
|
||||
Spring Security relies on Spring's localization support in order to actually lookup the appropriate message. In order for this to work, you have to make sure that the locale from the incoming request is stored in Spring's `org.springframework.context.i18n.LocaleContextHolder`. Spring MVC's `DispatcherServlet` does this for your application automatically, but since Spring Security's filters are invoked before this, the `LocaleContextHolder` needs to be set up to contain the correct `Locale` before the filters are called. You can either do this in a filter yourself (which must come before the Spring Security filters in`web.xml`) or you can use Spring's `RequestContextFilter`. Please refer to the Spring Framework documentation for further details on using localization with Spring.
|
||||
Spring Security relies on Spring's localization support in order to actually lookup the appropriate message. In order for this to work, you have to make sure that the locale from the incoming request is stored in Spring's `org.springframework.context.i18n.LocaleContextHolder`. Spring MVC's `DispatcherServlet` does this for your application automatically, but since Spring Security's filters are invoked before this, the `LocaleContextHolder` needs to be set up to contain the correct `Locale` before the filters are called. You can either do this in a filter yourself (which must come before the Spring Security filters in `web.xml`) or you can use Spring's `RequestContextFilter`. Please refer to the Spring Framework documentation for further details on using localization with Spring.
|
||||
|
||||
The "contacts" sample application is set up to use localized messages.
|
||||
|
||||
|
@ -2371,7 +2371,7 @@ As mentioned in the earlier in this reference guide, most authentication provide
|
|||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||
----
|
||||
|
||||
The returned `UserDetails` is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled. Most authentication providers will use a`UserDetailsService`, even if the username and password are not actually used as part of the authentication decision. They may use the returned `UserDetails` object just for its `GrantedAuthority` information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials.
|
||||
The returned `UserDetails` is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled. Most authentication providers will use a `UserDetailsService`, even if the username and password are not actually used as part of the authentication decision. They may use the returned `UserDetails` object just for its `GrantedAuthority` information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials.
|
||||
|
||||
Given `UserDetailsService` is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice. Having said that, Spring Security does include a couple of useful base implementations, which we'll look at below.
|
||||
|
||||
|
@ -2561,7 +2561,7 @@ The Servlet Specification defines several properties for the `HttpServletRequest
|
|||
|
||||
As mentioned above, the default strategy is to use Ant-style paths for matching and this is likely to be the best choice for most users. The strategy is implemented in the class `AntPathRequestMatcher` which uses Spring's `AntPathMatcher` to perform a case-insensitive match of the pattern against the concatenated `servletPath` and `pathInfo`, ignoring the `queryString`.
|
||||
|
||||
If for some reason, you need a more powerful matching strategy, you can use regular expressions. The strategy implementation is then`RegexRequestMatcher`. See the Javadoc for this class for more information.
|
||||
If for some reason, you need a more powerful matching strategy, you can use regular expressions. The strategy implementation is then `RegexRequestMatcher`. See the Javadoc for this class for more information.
|
||||
|
||||
In practice we recommend that you use method security at your service layer, to control access to your application, and do not rely entirely on the use of security constraints defined at the web-application level. URLs change and it is difficult to take account of all the possible URLs that an application might support and how requests might be manipulated. You should try and restrict yourself to using a few simple ant paths which are simple to understand. Always try to use a"deny-by-default" approach where you have a catch-all wildcard ( /** or **) defined last and denying access.
|
||||
|
||||
|
@ -2602,7 +2602,7 @@ There are some key filters which will always be used in a web application which
|
|||
|
||||
[[filter-security-interceptor]]
|
||||
=== FilterSecurityInterceptor
|
||||
We've already seen `FilterSecurityInterceptor` briefly when discussing <<tech-intro-access-control,access-control in general>>, and we've already used it with the namespace where the `<intercept-url>` elements are combined to configure it internally. Now we'll see how to explicitly configure it for use with a`FilterChainProxy`, along with its companion filter `ExceptionTranslationFilter`. A typical configuration example is shown below:
|
||||
We've already seen `FilterSecurityInterceptor` briefly when discussing <<tech-intro-access-control,access-control in general>>, and we've already used it with the namespace where the `<intercept-url>` elements are combined to configure it internally. Now we'll see how to explicitly configure it for use with a `FilterChainProxy`, along with its companion filter `ExceptionTranslationFilter`. A typical configuration example is shown below:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -2621,9 +2621,9 @@ We've already seen `FilterSecurityInterceptor` briefly when discussing <<tech-in
|
|||
|
||||
`FilterSecurityInterceptor` is responsible for handling the security of HTTP resources. It requires a reference to an `AuthenticationManager` and an `AccessDecisionManager`. It is also supplied with configuration attributes that apply to different HTTP URL requests. Refer back to <<tech-intro-config-attributes,the original discussion on these>> in the technical introduction.
|
||||
|
||||
The `FilterSecurityInterceptor` can be configured with configuration attributes in two ways. The first, which is shown above, is using the `<filter-security-metadata-source>` namespace element. This is similar to the `<http>` element from the namespace chapter but the `<intercept-url>` child elements only use the `pattern` and `access` attributes. Commas are used to delimit the different configuration attributes that apply to each HTTP URL. The second option is to write your own`SecurityMetadataSource`, but this is beyond the scope of this document. Irrespective of the approach used, the `SecurityMetadataSource` is responsible for returning a `List<ConfigAttribute>` containing all of the configuration attributes associated with a single secure HTTP URL.
|
||||
The `FilterSecurityInterceptor` can be configured with configuration attributes in two ways. The first, which is shown above, is using the `<filter-security-metadata-source>` namespace element. This is similar to the `<http>` element from the namespace chapter but the `<intercept-url>` child elements only use the `pattern` and `access` attributes. Commas are used to delimit the different configuration attributes that apply to each HTTP URL. The second option is to write your own `SecurityMetadataSource`, but this is beyond the scope of this document. Irrespective of the approach used, the `SecurityMetadataSource` is responsible for returning a `List<ConfigAttribute>` containing all of the configuration attributes associated with a single secure HTTP URL.
|
||||
|
||||
It should be noted that the `FilterSecurityInterceptor.setSecurityMetadataSource()` method actually expects an instance of `FilterInvocationSecurityMetadataSource`. This is a marker interface which subclasses`SecurityMetadataSource`. It simply denotes the `SecurityMetadataSource` understands `FilterInvocation` s. In the interests of simplicity we'll continue to refer to the `FilterInvocationSecurityMetadataSource` as a `SecurityMetadataSource`, as the distinction is of little relevance to most users.
|
||||
It should be noted that the `FilterSecurityInterceptor.setSecurityMetadataSource()` method actually expects an instance of `FilterInvocationSecurityMetadataSource`. This is a marker interface which subclasses `SecurityMetadataSource`. It simply denotes the `SecurityMetadataSource` understands `FilterInvocation` s. In the interests of simplicity we'll continue to refer to the `FilterInvocationSecurityMetadataSource` as a `SecurityMetadataSource`, as the distinction is of little relevance to most users.
|
||||
|
||||
The `SecurityMetadataSource` created by the namespace syntax obtains the configuration attributes for a particular `FilterInvocation` by matching the request URL against the configured `pattern` attributes. This behaves in the same way as it does for namespace configuration. The default is to treat all expressions as Apache Ant paths and regular expressions are also supported for more complex cases. The `request-matcher` attribute is used to specify the type of pattern being used. It is not possible to mix expression syntaxes within the same definition. As an example, the previous configuration using regular expressions instead of Ant paths would be written as follows:
|
||||
|
||||
|
@ -2725,7 +2725,7 @@ void saveContext(SecurityContext context, HttpServletRequest request,
|
|||
|
||||
The `HttpRequestResponseHolder` is simply a container for the incoming request and response objects, allowing the implementation to replace these with wrapper classes. The returned contents will be passed to the filter chain.
|
||||
|
||||
The default implementation is `HttpSessionSecurityContextRepository`, which stores the security context as an `HttpSession` attribute footnote:[In Spring Security 2.0 and earlier, this filter was called `HttpSessionContextIntegrationFilter` and performed all the work of storing the context was performed by the filter itself. If you were familiar with this class, then most of the configuration options which were available can now be found on`HttpSessionSecurityContextRepository`.]. The most important configuration parameter for this implementation is the `allowSessionCreation` property, which defaults to `true`, thus allowing the class to create a session if it needs one to store the security context for an authenticated user (it won't create one unless authentication has taken place and the contents of the security context have changed). If you don't want a session to be created, then you can set this property to `false`:
|
||||
The default implementation is `HttpSessionSecurityContextRepository`, which stores the security context as an `HttpSession` attribute footnote:[In Spring Security 2.0 and earlier, this filter was called `HttpSessionContextIntegrationFilter` and performed all the work of storing the context was performed by the filter itself. If you were familiar with this class, then most of the configuration options which were available can now be found on `HttpSessionSecurityContextRepository`.]. The most important configuration parameter for this implementation is the `allowSessionCreation` property, which defaults to `true`, thus allowing the class to create a session if it needs one to store the security context for an authenticated user (it won't create one unless authentication has taken place and the contents of the security context have changed). If you don't want a session to be created, then you can set this property to `false`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -2970,7 +2970,7 @@ class="org.springframework.security.web.authentication.www.BasicAuthenticationEn
|
|||
</bean>
|
||||
----
|
||||
|
||||
The configured `AuthenticationManager` processes each authentication request. If authentication fails, the configured `AuthenticationEntryPoint` will be used to retry the authentication process. Usually you will use the filter in combination with a`BasicAuthenticationEntryPoint`, which returns a 401 response with a suitable header to retry HTTP Basic authentication. If authentication is successful, the resulting `Authentication` object will be placed into the `SecurityContextHolder` as usual.
|
||||
The configured `AuthenticationManager` processes each authentication request. If authentication fails, the configured `AuthenticationEntryPoint` will be used to retry the authentication process. Usually you will use the filter in combination with a `BasicAuthenticationEntryPoint`, which returns a 401 response with a suitable header to retry HTTP Basic authentication. If authentication is successful, the resulting `Authentication` object will be placed into the `SecurityContextHolder` as usual.
|
||||
|
||||
If the authentication event was successful, or authentication was not attempted because the HTTP header did not contain a supported authentication request, the filter chain will continue as normal. The only time the filter chain will be interrupted is if authentication fails and the `AuthenticationEntryPoint` is called.
|
||||
|
||||
|
@ -3042,7 +3042,7 @@ This approach uses hashing to achieve a useful remember-me strategy. In essence
|
|||
base64(username + ":" + expirationTime + ":" +
|
||||
md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
|
||||
|
||||
username: As identifiable to the `UserDetailsService`
|
||||
username: As identifiable to the UserDetailsService
|
||||
password: That matches the one in the retrieved UserDetails
|
||||
expirationTime: The date and time when the remember-me token expires, expressed in milliseconds
|
||||
key: A private key to prevent modification of the remember-me token
|
||||
|
@ -4132,10 +4132,10 @@ HTTP session related functonality is handled by a combination of the `SessionMan
|
|||
|
||||
=== SessionManagementFilter
|
||||
The `SessionManagementFilter` checks the contents of the `SecurityContextRepository` against the current contents of the `SecurityContextHolder` to determine whether a user has been authenticated during the current request, typically by a non-interactive authentication mechanism, such as pre-authentication or remember-me footnote:[
|
||||
Authentication by mechanisms which perform a redirect after authenticating (such as form-login) will not be detected by`SessionManagementFilter`, as the filter will not be invoked during the authenticating request. Session-management functionality has to be handled separately in these cases.
|
||||
Authentication by mechanisms which perform a redirect after authenticating (such as form-login) will not be detected by `SessionManagementFilter`, as the filter will not be invoked during the authenticating request. Session-management functionality has to be handled separately in these cases.
|
||||
]. If the repository contains a security context, the filter does nothing. If it doesn't, and the thread-local `SecurityContext` contains a (non-anonymous) `Authentication` object, the filter assumes they have been authenticated by a previous filter in the stack. It will then invoke the configured `SessionAuthenticationStrategy`.
|
||||
|
||||
If the user is not currently authenticated, the filter will check whether an invalid session ID has been requested (because of a timeout, for example) and will invoke the configured`InvalidSessionStrategy`, if one is set. The most common behaviour is just to redirect to a fixed URL and this is encapsulated in the standard implementation`SimpleRedirectInvalidSessionStrategy`. The latter is also used when configuring an invalid session URL through the namespace,<<ns-session-mgmt,as described earlier>>.
|
||||
If the user is not currently authenticated, the filter will check whether an invalid session ID has been requested (because of a timeout, for example) and will invoke the configured `InvalidSessionStrategy`, if one is set. The most common behaviour is just to redirect to a fixed URL and this is encapsulated in the standard implementation `SimpleRedirectInvalidSessionStrategy`. The latter is also used when configuring an invalid session URL through the namespace,<<ns-session-mgmt,as described earlier>>.
|
||||
|
||||
|
||||
=== SessionAuthenticationStrategy
|
||||
|
@ -4376,7 +4376,7 @@ boolean supports(ConfigAttribute attribute);
|
|||
boolean supports(Class clazz);
|
||||
----
|
||||
|
||||
The `AccessDecisionManager`'s `decide` method is passed all the relevant information it needs in order to make an authorization decision. In particular, passing the secure `Object` enables those arguments contained in the actual secure object invocation to be inspected. For example, let's assume the secure object was a`MethodInvocation`. It would be easy to query the `MethodInvocation` for any `Customer` argument, and then implement some sort of security logic in the `AccessDecisionManager` to ensure the principal is permitted to operate on that customer. Implementations are expected to throw an `AccessDeniedException` if access is denied.
|
||||
The ``AccessDecisionManager``'s `decide` method is passed all the relevant information it needs in order to make an authorization decision. In particular, passing the secure `Object` enables those arguments contained in the actual secure object invocation to be inspected. For example, let's assume the secure object was a `MethodInvocation`. It would be easy to query the `MethodInvocation` for any `Customer` argument, and then implement some sort of security logic in the `AccessDecisionManager` to ensure the principal is permitted to operate on that customer. Implementations are expected to throw an `AccessDeniedException` if access is denied.
|
||||
|
||||
The `supports(ConfigAttribute)` method is called by the `AbstractSecurityInterceptor` at startup time to determine if the `AccessDecisionManager` can process the passed `ConfigAttribute`. The `supports(Class)` method is called by a security interceptor implementation to ensure the configured `AccessDecisionManager` supports the type of secure object that the security interceptor will present.
|
||||
|
||||
|
@ -4441,7 +4441,7 @@ image::images/after-invocation.png[]
|
|||
|
||||
Like many other parts of Spring Security, `AfterInvocationManager` has a single concrete implementation, `AfterInvocationProviderManager`, which polls a list of `AfterInvocationProvider` s. Each `AfterInvocationProvider` is allowed to modify the return object or throw an `AccessDeniedException`. Indeed multiple providers can modify the object, as the result of the previous provider is passed to the next in the list.
|
||||
|
||||
Please be aware that if you're using `AfterInvocationManager`, you will still need configuration attributes that allow the `MethodSecurityInterceptor`'s `AccessDecisionManager` to allow an operation. If you're using the typical Spring Security included `AccessDecisionManager` implementations, having no configuration attributes defined for a particular secure method invocation will cause each `AccessDecisionVoter` to abstain from voting. In turn, if the `AccessDecisionManager` property "`allowIfAllAbstainDecisions`" is `false`, an `AccessDeniedException` will be thrown. You may avoid this potential issue by either (i) setting "`allowIfAllAbstainDecisions`" to `true` (although this is generally not recommended) or (ii) simply ensure that there is at least one configuration attribute that an `AccessDecisionVoter` will vote to grant access for. This latter (recommended) approach is usually achieved through a `ROLE_USER` or `ROLE_AUTHENTICATED` configuration attribute.
|
||||
Please be aware that if you're using `AfterInvocationManager`, you will still need configuration attributes that allow the ``MethodSecurityInterceptor``'s `AccessDecisionManager` to allow an operation. If you're using the typical Spring Security included `AccessDecisionManager` implementations, having no configuration attributes defined for a particular secure method invocation will cause each `AccessDecisionVoter` to abstain from voting. In turn, if the `AccessDecisionManager` property "`allowIfAllAbstainDecisions`" is `false`, an `AccessDeniedException` will be thrown. You may avoid this potential issue by either (i) setting "`allowIfAllAbstainDecisions`" to `true` (although this is generally not recommended) or (ii) simply ensure that there is at least one configuration attribute that an `AccessDecisionVoter` will vote to grant access for. This latter (recommended) approach is usually achieved through a `ROLE_USER` or `ROLE_AUTHENTICATED` configuration attribute.
|
||||
|
||||
|
||||
[[authz-hierarchical-roles]]
|
||||
|
@ -4528,7 +4528,7 @@ Let's first consider how the `AspectJSecurityInterceptor` is configured in the S
|
|||
----
|
||||
|
||||
|
||||
As you can see, aside from the class name, the `AspectJSecurityInterceptor` is exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors can share the same`securityMetadataSource`, as the `SecurityMetadataSource` works with `java.lang.reflect.Method` s rather than an AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie `MethodInvocation` or `JoinPoint`) and as such can consider a range of addition criteria when making access decisions (such as method arguments).
|
||||
As you can see, aside from the class name, the `AspectJSecurityInterceptor` is exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors can share the same `securityMetadataSource`, as the `SecurityMetadataSource` works with `java.lang.reflect.Method` s rather than an AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie `MethodInvocation` or `JoinPoint`) and as such can consider a range of addition criteria when making access decisions (such as method arguments).
|
||||
|
||||
Next you'll need to define an AspectJ `aspect`. For example:
|
||||
|
||||
|
@ -4908,7 +4908,7 @@ To use `hasPermission()` expressions, you have to explicitly configure a `Permis
|
|||
</bean>
|
||||
----
|
||||
|
||||
Where `myPermissionEvaluator` is the bean which implements `PermissionEvaluator`. Usually this will be the implementation from the ACL module which is called`AclPermissionEvaluator`. See the "Contacts" sample application configuration for more details.
|
||||
Where `myPermissionEvaluator` is the bean which implements `PermissionEvaluator`. Usually this will be the implementation from the ACL module which is called `AclPermissionEvaluator`. See the "Contacts" sample application configuration for more details.
|
||||
|
||||
===== Method Security Meta Annotations
|
||||
|
||||
|
@ -4947,7 +4947,7 @@ Complex applications often will find the need to define access permissions not s
|
|||
Imagine you're designing an application for a pet clinic. There will be two main groups of users of your Spring-based application: staff of the pet clinic, as well as the pet clinic's customers. The staff will have access to all of the data, whilst your customers will only be able to see their own customer records. To make it a little more interesting, your customers can allow other users to see their customer records, such as their "puppy preschool" mentor or president of their local "Pony Club". Using Spring Security as the foundation, you have several approaches that can be used:
|
||||
|
||||
* Write your business methods to enforce the security. You could consult a collection within the `Customer` domain object instance to determine which users have access. By using the `SecurityContextHolder.getContext().getAuthentication()`, you'll be able to access the `Authentication` object.
|
||||
* Write an `AccessDecisionVoter` to enforce the security from the `GrantedAuthority[]` s stored in the `Authentication` object. This would mean your `AuthenticationManager` would need to populate the `Authentication` with custom `GrantedAuthority`[]s representing each of the `Customer` domain object instances the principal has access to.
|
||||
* Write an `AccessDecisionVoter` to enforce the security from the `GrantedAuthority[]` s stored in the `Authentication` object. This would mean your `AuthenticationManager` would need to populate the `Authentication` with custom ``GrantedAuthority[]``s representing each of the `Customer` domain object instances the principal has access to.
|
||||
* Write an `AccessDecisionVoter` to enforce the security and open the target `Customer` domain object directly. This would mean your voter needs access to a DAO that allows it to retrieve the `Customer` object. It would then access the `Customer` object's collection of approved users and make the appropriate decision.
|
||||
|
||||
|
||||
|
@ -4992,7 +4992,7 @@ Now that we've provided a basic overview of what the ACL system does, and what i
|
|||
|
||||
* `Acl`: Every domain object has one and only one `Acl` object, which internally holds the `AccessControlEntry` s as well as knows the owner of the `Acl`. An Acl does not refer directly to the domain object, but instead to an `ObjectIdentity`. The `Acl` is stored in the ACL_OBJECT_IDENTITY table.
|
||||
|
||||
* `AccessControlEntry`: An `Acl` holds multiple `AccessControlEntry` s, which are often abbreviated as ACEs in the framework. Each ACE refers to a specific tuple of`Permission`, `Sid` and `Acl`. An ACE can also be granting or non-granting and contain audit settings. The ACE is stored in the ACL_ENTRY table.
|
||||
* `AccessControlEntry`: An `Acl` holds multiple `AccessControlEntry` s, which are often abbreviated as ACEs in the framework. Each ACE refers to a specific tuple of `Permission`, `Sid` and `Acl`. An ACE can also be granting or non-granting and contain audit settings. The ACE is stored in the ACL_ENTRY table.
|
||||
|
||||
* `Permission`: A permission represents a particular immutable bit mask, and offers convenience functions for bit masking and outputting information. The basic permissions presented above (bits 0 through 4) are contained in the `BasePermission` class.
|
||||
|
||||
|
@ -5017,7 +5017,7 @@ To get starting using Spring Security's ACL capability, you will need to store y
|
|||
|
||||
Once you've created the required schema and instantiated `JdbcMutableAclService`, you'll next need to ensure your domain model supports interoperability with the Spring Security ACL package. Hopefully `ObjectIdentityImpl` will prove sufficient, as it provides a large number of ways in which it can be used. Most people will have domain objects that contain a `public Serializable getId()` method. If the return type is long, or compatible with long (eg an int), you will find you need not give further consideration to `ObjectIdentity` issues. Many parts of the ACL module rely on long identifiers. If you're not using long (or an int, byte etc), there is a very good chance you'll need to reimplement a number of classes. We do not intend to support non-long identifiers in Spring Security's ACL module, as longs are already compatible with all database sequences, the most common identifier data type, and are of sufficient length to accommodate all common usage scenarios.
|
||||
|
||||
The following fragment of code shows how to create an `Acl`, or modify an existing`Acl`:
|
||||
The following fragment of code shows how to create an `Acl`, or modify an existing `Acl`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -5170,7 +5170,7 @@ When using LDAP authentication, it is important to ensure that you configure LDA
|
|||
=== Using LDAP with Spring Security
|
||||
LDAP authentication in Spring Security can be roughly divided into the following stages.
|
||||
|
||||
* Obtaining the unique LDAP "Distinguished Name", or DN, from the login name. This will often mean performing a search in the directory, unless the exact mapping of usernames to DNs is known in advance. So a user might enter the name "joe" when logging in, but the actual name used to authenticate to LDAP will be the full DN, such as`uid=joe,ou=users,dc=spring,dc=io`.
|
||||
* Obtaining the unique LDAP "Distinguished Name", or DN, from the login name. This will often mean performing a search in the directory, unless the exact mapping of usernames to DNs is known in advance. So a user might enter the name "joe" when logging in, but the actual name used to authenticate to LDAP will be the full DN, such as `uid=joe,ou=users,dc=spring,dc=io`.
|
||||
|
||||
* Authenticating the user, either by "binding" as that user or by performing a remote "compare" operation of the user's password against the password attribute in the directory entry for the DN.
|
||||
|
||||
|
@ -5229,8 +5229,8 @@ If used with the server definition above, this would perform a search under the
|
|||
How authorities are loaded from groups in the LDAP directory is controlled by the following attributes.
|
||||
|
||||
* `group-search-base`. Defines the part of the directory tree under which group searches should be performed.
|
||||
* `group-role-attribute`. The attribute which contains the name of the authority defined by the group entry. Defaults to`cn`
|
||||
* `group-search-filter`. The filter which is used to search for group membership. The default is`uniqueMember={0}`, corresponding to the `groupOfUniqueNames` LDAP class footnote:[Note that this is different from the default configuration of the underlying `DefaultLdapAuthoritiesPopulator` which uses `member={0}`.]. In this case, the substituted parameter is the full distinguished name of the user. The parameter `{1}` can be used if you want to filter on the login name.
|
||||
* `group-role-attribute`. The attribute which contains the name of the authority defined by the group entry. Defaults to `cn`
|
||||
* `group-search-filter`. The filter which is used to search for group membership. The default is `uniqueMember={0}`, corresponding to the `groupOfUniqueNames` LDAP class footnote:[Note that this is different from the default configuration of the underlying `DefaultLdapAuthoritiesPopulator` which uses `member={0}`.]. In this case, the substituted parameter is the full distinguished name of the user. The parameter `{1}` can be used if you want to filter on the login name.
|
||||
|
||||
So if we used the following configuration
|
||||
|
||||
|
@ -5240,7 +5240,7 @@ So if we used the following configuration
|
|||
group-search-base="ou=groups" />
|
||||
----
|
||||
|
||||
and authenticated successfully as user "ben", the subsequent loading of authorities would perform a search under the directory entry`ou=groups,dc=springframework,dc=org`, looking for entries which contain the attribute `uniqueMember` with value `uid=ben,ou=people,dc=springframework,dc=org`. By default the authority names will have the prefix `ROLE_` prepended. You can change this using the `role-prefix` attribute. If you don't want any prefix, use `role-prefix="none"`. For more information on loading authorities, see the Javadoc for the `DefaultLdapAuthoritiesPopulator` class.
|
||||
and authenticated successfully as user "ben", the subsequent loading of authorities would perform a search under the directory entry `ou=groups,dc=springframework,dc=org`, looking for entries which contain the attribute `uniqueMember` with value `uid=ben,ou=people,dc=springframework,dc=org`. By default the authority names will have the prefix `ROLE_` prepended. You can change this using the `role-prefix` attribute. If you don't want any prefix, use `role-prefix="none"`. For more information on loading authorities, see the Javadoc for the `DefaultLdapAuthoritiesPopulator` class.
|
||||
|
||||
=== Implementation Classes
|
||||
The namespace configuration options we've used above are simple to use and much more concise than using Spring beans explicitly. There are situations when you may need to know how to configure Spring Security LDAP directly in your application context. You may wish to customize the behaviour of some of the classes, for example. If you're happy using namespace configuration then you can skip this section and the next one.
|
||||
|
@ -5260,7 +5260,7 @@ There are currently two authentication strategies supplied with Spring Security:
|
|||
|
||||
[[ldap-ldap-authenticators-common]]
|
||||
===== Common Functionality
|
||||
Before it is possible to authenticate a user (by either strategy), the distinguished name (DN) has to be obtained from the login name supplied to the application. This can be done either by simple pattern-matching (by setting the `setUserDnPatterns` array property) or by setting the `userSearch` property. For the DN pattern-matching approach, a standard Java pattern format is used, and the login name will be substituted for the parameter `{0}`. The pattern should be relative to the DN that the configured `SpringSecurityContextSource` will bind to (see the section on <<ldap-context-source,connecting to the LDAP server>> for more information on this). For example, if you are using an LDAP server with the URL`ldap://monkeymachine.co.uk/dc=springframework,dc=org`, and have a pattern `uid={0},ou=greatapes`, then a login name of "gorilla" will map to a DN`uid=gorilla,ou=greatapes,dc=springframework,dc=org`. Each configured DN pattern will be tried in turn until a match is found. For information on using a search, see the section on <<ldap-searchobjects,search objects>> below. A combination of the two approaches can also be used - the patterns will be checked first and if no matching DN is found, the search will be used.
|
||||
Before it is possible to authenticate a user (by either strategy), the distinguished name (DN) has to be obtained from the login name supplied to the application. This can be done either by simple pattern-matching (by setting the `setUserDnPatterns` array property) or by setting the `userSearch` property. For the DN pattern-matching approach, a standard Java pattern format is used, and the login name will be substituted for the parameter `{0}`. The pattern should be relative to the DN that the configured `SpringSecurityContextSource` will bind to (see the section on <<ldap-context-source,connecting to the LDAP server>> for more information on this). For example, if you are using an LDAP server with the URL `ldap://monkeymachine.co.uk/dc=springframework,dc=org`, and have a pattern `uid={0},ou=greatapes`, then a login name of "gorilla" will map to a DN `uid=gorilla,ou=greatapes,dc=springframework,dc=org`. Each configured DN pattern will be tried in turn until a match is found. For information on using a search, see the section on <<ldap-searchobjects,search objects>> below. A combination of the two approaches can also be used - the patterns will be checked first and if no matching DN is found, the search will be used.
|
||||
|
||||
|
||||
[[ldap-ldap-authenticators-bind]]
|
||||
|
@ -5328,7 +5328,7 @@ A typical configuration, using some of the beans we've discussed here, might loo
|
|||
</bean>
|
||||
----
|
||||
|
||||
This would set up the provider to access an LDAP server with URL `ldap://monkeymachine:389/dc=springframework,dc=org`. Authentication will be performed by attempting to bind with the DN`uid=<user-login-name>,ou=people,dc=springframework,dc=org`. After successful authentication, roles will be assigned to the user by searching under the DN `ou=groups,dc=springframework,dc=org` with the default filter `(member=<user's-DN>)`. The role name will be taken from the "ou" attribute of each match.
|
||||
This would set up the provider to access an LDAP server with URL `ldap://monkeymachine:389/dc=springframework,dc=org`. Authentication will be performed by attempting to bind with the DN `uid=<user-login-name>,ou=people,dc=springframework,dc=org`. After successful authentication, roles will be assigned to the user by searching under the DN `ou=groups,dc=springframework,dc=org` with the default filter `(member=<user's-DN>)`. The role name will be taken from the "ou" attribute of each match.
|
||||
|
||||
To configure a user search object, which uses the filter `(uid=<user-login-name>)` for use instead of the DN-pattern (or in addition to it), you would configure the following bean
|
||||
|
||||
|
@ -5361,7 +5361,7 @@ void mapUserToContext(UserDetails user, DirContextAdapter ctx);
|
|||
}
|
||||
----
|
||||
|
||||
Only the first method is relevant for authentication. If you provide an implementation of this interface and inject it into the `LdapAuthenticationProvider`, you have control over exactly how the UserDetails object is created. The first parameter is an instance of Spring LDAP's `DirContextOperations` which gives you access to the LDAP attributes which were loaded during authentication. the `username` parameter is the name used to authenticate and the final parameter is the collection of authorities loaded for the user by the configured`LdapAuthoritiesPopulator`.
|
||||
Only the first method is relevant for authentication. If you provide an implementation of this interface and inject it into the `LdapAuthenticationProvider`, you have control over exactly how the UserDetails object is created. The first parameter is an instance of Spring LDAP's `DirContextOperations` which gives you access to the LDAP attributes which were loaded during authentication. the `username` parameter is the name used to authenticate and the final parameter is the collection of authorities loaded for the user by the configured `LdapAuthoritiesPopulator`.
|
||||
|
||||
The way the context data is loaded varies slightly depending on the type of authentication you are using. With the `BindAuthenticator`, the context returned from the bind operation will be used to read the attributes, otherwise the data will be read using the standard context obtained from the configured `ContextSource` (when a search is configured to locate the user, this will be the data returned by the search object).
|
||||
|
||||
|
@ -5741,7 +5741,7 @@ The basic interaction between a web browser, CAS server and a Spring Security-se
|
|||
* The `Cas20TicketValidator` will parse the XML received from the CAS server. It will return to the `CasAuthenticationProvider` a `TicketResponse`, which includes the username (mandatory), proxy list (if any were involved), and proxy-granting ticket IOU (if the proxy callback was requested).
|
||||
* Next `CasAuthenticationProvider` will call a configured `CasProxyDecider`. The `CasProxyDecider` indicates whether the proxy list in the `TicketResponse` is acceptable to the service. Several implementations are provided with Spring Security: `RejectProxyTickets`, `AcceptAnyCasProxy` and `NamedCasProxyDecider`. These names are largely self-explanatory, except `NamedCasProxyDecider` which allows a `List` of trusted proxies to be provided.
|
||||
* `CasAuthenticationProvider` will next request a `AuthenticationUserDetailsService` to load the `GrantedAuthority` objects that apply to the user contained in the `Assertion`.
|
||||
* If there were no problems, `CasAuthenticationProvider` constructs a `CasAuthenticationToken` including the details contained in the `TicketResponse` and the `GrantedAuthority`s.
|
||||
* If there were no problems, `CasAuthenticationProvider` constructs a `CasAuthenticationToken` including the details contained in the `TicketResponse` and the ``GrantedAuthority``s.
|
||||
* Control then returns to `CasAuthenticationFilter`, which places the created `CasAuthenticationToken` in the security context.
|
||||
* The user's browser is redirected to the original page that caused the `AuthenticationException` (or a <<form-login-flow-handling,custom destination>> depending on the configuration).
|
||||
|
||||
|
@ -6354,7 +6354,7 @@ executor.execute(originalRunnable);
|
|||
The code performs the following steps:
|
||||
|
||||
* Creates the `SecurityContext` to be used for our `DelegatingSecurityContextExecutor`. Note that in this example we simply create the `SecurityContext` by hand. However, it does not matter where or how we get the `SecurityContext` (i.e. we could obtain it from the `SecurityContextHolder` if we wanted).
|
||||
* Creates a delegateExecutor that is in charge of executing submitted `Runnable`s
|
||||
* Creates a delegateExecutor that is in charge of executing submitted ``Runnable``s
|
||||
* Finally we create a `DelegatingSecurityContextExecutor` which is in charge of wrapping any Runnable that is passed into the execute method with a `DelegatingSecurityContextRunnable`. It then passes the wrapped Runnable to the delegateExecutor. In this instance, the same `SecurityContext` will be used for every Runnable submitted to our `DelegatingSecurityContextExecutor`. This is nice if we are running background tasks that need to be run by a user with elevated privileges.
|
||||
* At this point you may be asking yourself "How does this shield my code of any knowledge of Spring Security?" Instead of creating the `SecurityContext` and the `DelegatingSecurityContextExecutor` in our own code, we can inject an already initialized instance of `DelegatingSecurityContextExecutor`.
|
||||
|
||||
|
@ -6373,7 +6373,7 @@ executor.execute(originalRunnable);
|
|||
}
|
||||
----
|
||||
|
||||
Now our code is unaware that the `SecurityContext` is being propagated to the `Thread`, then the `originalRunnable` is executed, and then the `SecurityContextHolder` is cleared out. In this example, the same user is being used to execute each Thread. What if we wanted to use the user from `SecurityContextHolder` at the time we invoked `executor.execute(Runnable)` (i.e. the currently logged in user) to process `originalRunnable`? This can be done by removing the `SecurityContext` argument from our `DelegatingSecurityContextExecutor` constructor. For example:
|
||||
Now our code is unaware that the `SecurityContext` is being propagated to the `Thread`, then the `originalRunnable` is executed, and then the `SecurityContextHolder` is cleared out. In this example, the same user is being used to execute each Thread. What if we wanted to use the user from `SecurityContextHolder` at the time we invoked `executor.execute(Runnable)` (i.e. the currently logged in user) to process ``originalRunnable``? This can be done by removing the `SecurityContext` argument from our `DelegatingSecurityContextExecutor` constructor. For example:
|
||||
|
||||
|
||||
[source,java]
|
||||
|
@ -7120,7 +7120,7 @@ The access denied page that an authenticated user will be redirected to if they
|
|||
|
||||
[[nsa-access-denied-handler-ref]]
|
||||
* **ref**
|
||||
Defines a reference to a Spring bean of type `AccessDeniedHandler `.
|
||||
Defines a reference to a Spring bean of type `AccessDeniedHandler`.
|
||||
|
||||
|
||||
[[nsa-headers]]
|
||||
|
@ -8424,7 +8424,7 @@ Unless used with a `ref` attribute, this element is shorthand for configuring a
|
|||
|
||||
[[nsa-authentication-provider-ref]]
|
||||
* **ref**
|
||||
Defines a reference to a Spring bean that implements `AuthenticationProvider `.
|
||||
Defines a reference to a Spring bean that implements `AuthenticationProvider`.
|
||||
|
||||
If you have written your own `AuthenticationProvider` implementation (or want to configure one of Spring Security's own implementations as a traditional bean for some reason, then you can use the following syntax to add it to the internal list of `ProviderManager`:
|
||||
|
||||
|
@ -8563,7 +8563,7 @@ Defines the hashing algorithm used on user passwords. We recommend strongly agai
|
|||
|
||||
[[nsa-password-encoder-ref]]
|
||||
* **ref**
|
||||
Defines a reference to a Spring bean that implements `PasswordEncoder `.
|
||||
Defines a reference to a Spring bean that implements `PasswordEncoder`.
|
||||
|
||||
|
||||
[[nsa-password-encoder-children]]
|
||||
|
@ -8779,7 +8779,7 @@ This element can be used to decorate an `AfterInvocationProvider` for use by the
|
|||
|
||||
[[nsa-after-invocation-provider-ref]]
|
||||
* **ref**
|
||||
Defines a reference to a Spring bean that implements ` AfterInvocationProvider`.
|
||||
Defines a reference to a Spring bean that implements `AfterInvocationProvider`.
|
||||
|
||||
|
||||
[[nsa-pre-post-annotation-handling]]
|
||||
|
@ -9047,22 +9047,22 @@ This element is shorthand for the creation of an `LdapAuthenticationProvider` in
|
|||
|
||||
[[nsa-ldap-authentication-provider-group-role-attribute]]
|
||||
* **group-role-attribute**
|
||||
The LDAP attribute name which contains the role name which will be used within Spring Security. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupRoleAttribute` property. Defaults to "cn".
|
||||
The LDAP attribute name which contains the role name which will be used within Spring Security. Maps to the ``DefaultLdapAuthoritiesPopulator``'s `groupRoleAttribute` property. Defaults to "cn".
|
||||
|
||||
|
||||
[[nsa-ldap-authentication-provider-group-search-base]]
|
||||
* **group-search-base**
|
||||
Search base for group membership searches. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupSearchBase` constructor argument. Defaults to "" (searching from the root).
|
||||
Search base for group membership searches. Maps to the ``DefaultLdapAuthoritiesPopulator``'s `groupSearchBase` constructor argument. Defaults to "" (searching from the root).
|
||||
|
||||
|
||||
[[nsa-ldap-authentication-provider-group-search-filter]]
|
||||
* **group-search-filter**
|
||||
Group search filter. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupSearchFilter` property. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
|
||||
Group search filter. Maps to the ``DefaultLdapAuthoritiesPopulator``'s `groupSearchFilter` property. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
|
||||
|
||||
|
||||
[[nsa-ldap-authentication-provider-role-prefix]]
|
||||
* **role-prefix**
|
||||
A non-empty string prefix that will be added to role strings loaded from persistent. Maps to the `DefaultLdapAuthoritiesPopulator`'s `rolePrefix` property. Defaults to "ROLE_". Use the value "none" for no prefix in cases where the default is non-empty.
|
||||
A non-empty string prefix that will be added to role strings loaded from persistent. Maps to the ``DefaultLdapAuthoritiesPopulator``'s `rolePrefix` property. Defaults to "ROLE_". Use the value "none" for no prefix in cases where the default is non-empty.
|
||||
|
||||
|
||||
[[nsa-ldap-authentication-provider-server-ref]]
|
||||
|
|
Loading…
Reference in New Issue