mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-29 00:02:12 +00:00
Restructure Docs
Issue gh-5935
This commit is contained in:
parent
c5fd646afc
commit
4fa1d08e20
@ -1,30 +0,0 @@
|
||||
|
||||
[[advanced-topics]]
|
||||
= Additional Topics
|
||||
In this part we cover features which require knowledge of previous chapters as well as some of the more advanced and less-commonly used features of the framework.
|
||||
|
||||
include::acls.adoc[]
|
||||
|
||||
include::preauth.adoc[]
|
||||
|
||||
include::ldap.adoc[]
|
||||
|
||||
include::oauth2.adoc[]
|
||||
|
||||
include::webclient.adoc[]
|
||||
|
||||
include::jsp-taglibs.adoc[]
|
||||
|
||||
include::jaas.adoc[]
|
||||
|
||||
include::cas.adoc[]
|
||||
|
||||
include::x509.adoc[]
|
||||
|
||||
include::runas.adoc[]
|
||||
|
||||
include::crypto.adoc[]
|
||||
|
||||
include::concurrency.adoc[]
|
||||
|
||||
include::mvc.adoc[]
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[core-web-filters]]
|
||||
== Core Security Filters
|
||||
There are some key filters which will always be used in a web application which uses Spring Security, so we'll look at these and their supporting classes and interfaces first.
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[core-services]]
|
||||
== Core Services
|
||||
Now that we have a high-level overview of the Spring Security architecture and its core classes, let's take a closer look at one or two of the core interfaces and their implementations, in particular the `AuthenticationManager`, `UserDetailsService` and the `AccessDecisionManager`.
|
||||
@ -172,7 +171,3 @@ Some people prefer this approach as a means of administering user rights.
|
||||
See the `JdbcDaoImpl` Javadoc for more information on how to enable the use of group authorities.
|
||||
The group schema is also included in the appendix.
|
||||
|
||||
include::password-encoder.adoc[leveloffset=+2]
|
||||
|
||||
include::jackson.adoc[]
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[security-filter-chain]]
|
||||
== The Security Filter Chain
|
||||
Spring Security's web infrastructure is based entirely on standard servlet filters.
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[technical-overview]]
|
||||
== Technical Overview
|
||||
|
||||
@ -422,41 +421,3 @@ Only developers contemplating an entirely new way of intercepting and authorizin
|
||||
For example, it would be possible to build a new secure object to secure calls to a messaging system.
|
||||
Anything that requires security and also provides a way of intercepting a call (like the AOP around advice semantics) is capable of being made into a secure object.
|
||||
Having said that, most Spring applications will simply use the three currently supported secure object types (AOP Alliance `MethodInvocation`, AspectJ `JoinPoint` and web request `FilterInvocation`) with complete transparency.
|
||||
|
||||
|
||||
[[localization]]
|
||||
=== Localization
|
||||
Spring Security supports localization of exception messages that end users are likely to see.
|
||||
If your application is designed for English-speaking users, you don't need to do anything as by default all Security messages are in English.
|
||||
If you need to support other locales, everything you need to know is contained in this section.
|
||||
|
||||
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:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="messageSource"
|
||||
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
||||
<property name="basename" value="classpath:org/springframework/security/messages"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
The `messages.properties` is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages.
|
||||
This default file is in English.
|
||||
|
||||
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.
|
||||
|
||||
The "contacts" sample application is set up to use localized messages.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[anonymous]]
|
||||
== Anonymous Authentication
|
||||
|
@ -0,0 +1,7 @@
|
||||
[[ns-entry-point-ref]]
|
||||
== Setting a Custom AuthenticationEntryPoint
|
||||
If you aren't using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we've just seen.
|
||||
The corresponding `AuthenticationEntryPoint` can be set using the `entry-point-ref` attribute on the `<http>` element.
|
||||
|
||||
The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax.
|
||||
If you aren't familiar with authentication entry points, they are discussed in the <<tech-intro-auth-entry-point,technical overview>> chapter.
|
@ -0,0 +1,38 @@
|
||||
[[ns-auth-manager]]
|
||||
== The Authentication Manager and the Namespace
|
||||
The main interface which provides authentication services in Spring Security is the `AuthenticationManager`.
|
||||
This is usually an instance of Spring Security's `ProviderManager` class, which you may already be familiar with if you've used the framework before.
|
||||
If not, it will be covered later, in the <<tech-intro-authentication,technical overview chapter>>.
|
||||
The bean instance is registered using the `authentication-manager` namespace element.
|
||||
You can't use a custom `AuthenticationManager` if you are using either HTTP or method security through the namespace, but this should not be a problem as you have full control over the `AuthenticationProvider` s that are used.
|
||||
|
||||
You may want to register additional `AuthenticationProvider` beans with the `ProviderManager` and you can do this using the `<authentication-provider>` element with the `ref` attribute, where the value of the attribute is the name of the provider bean you want to add.
|
||||
For example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider ref="casAuthenticationProvider"/>
|
||||
</authentication-manager>
|
||||
|
||||
<bean id="casAuthenticationProvider"
|
||||
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
|
||||
...
|
||||
</bean>
|
||||
----
|
||||
|
||||
Another common requirement is that another bean in the context may require a reference to the `AuthenticationManager`.
|
||||
You can easily register an alias for the `AuthenticationManager` and use this name elsewhere in your application context.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<security:authentication-manager alias="authenticationManager">
|
||||
...
|
||||
</security:authentication-manager>
|
||||
|
||||
<bean id="customizedFormLoginFilter"
|
||||
class="com.somecompany.security.web.CustomFormLoginFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
...
|
||||
</bean>
|
||||
----
|
@ -0,0 +1,73 @@
|
||||
[[jc-authentication-authenticationprovider]]
|
||||
== AuthenticationProvider
|
||||
|
||||
=== AuthenticationProvider Java Configuration
|
||||
You can define custom authentication by exposing a custom `AuthenticationProvider` as a bean.
|
||||
For example, the following will customize authentication assuming that `SpringAuthenticationProvider` implements `AuthenticationProvider`:
|
||||
|
||||
NOTE: This is only used if the `AuthenticationManagerBuilder` has not been populated
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public SpringAuthenticationProvider springAuthenticationProvider() {
|
||||
return new SpringAuthenticationProvider();
|
||||
}
|
||||
----
|
||||
|
||||
[[ns-auth-providers]]
|
||||
=== AuthenticationProvider XML Configuration
|
||||
In practice you will need a more scalable source of user information than a few names added to the application context file.
|
||||
Most likely you will want to store your user information in something like a database or an LDAP server.
|
||||
LDAP namespace configuration is dealt with in the <<ldap,LDAP chapter>>, so we won't cover it here.
|
||||
If you have a custom implementation of Spring Security's `UserDetailsService`, called "myUserDetailsService" in your application context, then you can authenticate against this using
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider user-service-ref='myUserDetailsService'/>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
If you want to use a database, then you can use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<jdbc-user-service data-source-ref="securityDataSource"/>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
Where "securityDataSource" is the name of a `DataSource` bean in the application context, pointing at a database containing the standard Spring Security <<user-schema,user data tables>>.
|
||||
Alternatively, you could configure a Spring Security `JdbcDaoImpl` bean and point at that using the `user-service-ref` attribute:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider user-service-ref='myUserDetailsService'/>
|
||||
</authentication-manager>
|
||||
|
||||
<beans:bean id="myUserDetailsService"
|
||||
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
|
||||
<beans:property name="dataSource" ref="dataSource"/>
|
||||
</beans:bean>
|
||||
----
|
||||
|
||||
You can also use standard `AuthenticationProvider` beans as follows
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider ref='myAuthenticationProvider'/>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
where `myAuthenticationProvider` is the name of a bean in your application context which implements `AuthenticationProvider`.
|
||||
You can use multiple `authentication-provider` elements, in which case the providers will be queried in the order they are declared.
|
||||
See <<ns-auth-manager>> for more information on how the Spring Security `AuthenticationManager` is configured using the namespace.
|
@ -0,0 +1,41 @@
|
||||
[[basic]]
|
||||
== Basic and Digest Authentication
|
||||
Basic and digest authentication are alternative authentication mechanisms which are popular in web applications.
|
||||
Basic authentication is often used with stateless clients which pass their credentials on each request.
|
||||
It's quite common to use it in combination with form-based authentication where an application is used through both a browser-based user interface and as a web-service.
|
||||
However, basic authentication transmits the password as plain text so it should only really be used over an encrypted transport layer such as HTTPS.
|
||||
|
||||
[[basic-processing-filter]]
|
||||
=== BasicAuthenticationFilter
|
||||
`BasicAuthenticationFilter` is responsible for processing basic authentication credentials presented in HTTP headers.
|
||||
This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet Explorer).
|
||||
The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and `BasicAuthenticationFilter` conforms with this RFC.
|
||||
Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it's just a Base64 encoding of the username:password, specified in an HTTP header).
|
||||
|
||||
[[basic-config]]
|
||||
=== Configuration
|
||||
To implement HTTP Basic Authentication, you need to add a `BasicAuthenticationFilter` to your filter chain.
|
||||
The application context should contain `BasicAuthenticationFilter` and its required collaborator:
|
||||
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="basicAuthenticationFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
|
||||
<property name="realmName" value="Name Of Your Realm"/>
|
||||
</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.
|
||||
|
||||
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.
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
[[cas]]
|
||||
== CAS Authentication
|
||||
|
@ -1,48 +1,6 @@
|
||||
|
||||
[[basic]]
|
||||
== Basic and Digest Authentication
|
||||
Basic and digest authentication are alternative authentication mechanisms which are popular in web applications.
|
||||
Basic authentication is often used with stateless clients which pass their credentials on each request.
|
||||
It's quite common to use it in combination with form-based authentication where an application is used through both a browser-based user interface and as a web-service.
|
||||
However, basic authentication transmits the password as plain text so it should only really be used over an encrypted transport layer such as HTTPS.
|
||||
|
||||
[[basic-processing-filter]]
|
||||
=== BasicAuthenticationFilter
|
||||
`BasicAuthenticationFilter` is responsible for processing basic authentication credentials presented in HTTP headers.
|
||||
This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet Explorer).
|
||||
The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and `BasicAuthenticationFilter` conforms with this RFC.
|
||||
Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it's just a Base64 encoding of the username:password, specified in an HTTP header).
|
||||
|
||||
[[basic-config]]
|
||||
==== Configuration
|
||||
To implement HTTP Basic Authentication, you need to add a `BasicAuthenticationFilter` to your filter chain.
|
||||
The application context should contain `BasicAuthenticationFilter` and its required collaborator:
|
||||
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="basicAuthenticationFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
|
||||
<property name="realmName" value="Name Of Your Realm"/>
|
||||
</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.
|
||||
|
||||
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.
|
||||
|
||||
[[digest-processing-filter]]
|
||||
=== DigestAuthenticationFilter
|
||||
== DigestAuthenticationFilter
|
||||
`DigestAuthenticationFilter` is capable of processing digest authentication credentials presented in HTTP headers.
|
||||
Digest Authentication attempts to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire.
|
||||
Many user agents support Digest Authentication, including Mozilla Firefox and Internet Explorer.
|
||||
@ -88,7 +46,7 @@ In our testing, Spring Security's implementation works reliably with Mozilla Fir
|
||||
|
||||
|
||||
[[digest-config]]
|
||||
==== Configuration
|
||||
=== Configuration
|
||||
Now that we've reviewed the theory, let's see how to use it.
|
||||
To implement HTTP Digest Authentication, it is necessary to define `DigestAuthenticationFilter` in the filter chain.
|
||||
The application context will need to define the `DigestAuthenticationFilter` and its required collaborators:
|
@ -0,0 +1,138 @@
|
||||
[[jc-form]]
|
||||
== Form Login
|
||||
|
||||
=== Form Login Java Configuration
|
||||
|
||||
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs.
|
||||
Since Spring Security's default configuration does not explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.
|
||||
|
||||
While the automatically generated log in page is convenient to get up and running quickly, most applications will want to provide their own login page.
|
||||
When we want to change the default configuration, we can customize the `WebSecurityConfigurerAdapter` that we mentioned earlier by extending it like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
And then override the `configure` method as seen below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(formLogin ->
|
||||
formLogin
|
||||
.loginPage("/login") // <1>
|
||||
.permitAll() // <2>
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
<1> The updated configuration specifies the location of the log in page.
|
||||
<2> We must grant all users (i.e. unauthenticated users) access to our log in page.
|
||||
The `formLogin().permitAll()` method allows granting access to all users for all URLs associated with form based log in.
|
||||
|
||||
An example log in page implemented with JSPs for our current configuration can be seen below:
|
||||
|
||||
NOTE: The login page below represents our current configuration.
|
||||
We could easily update our configuration if some of the defaults do not meet our needs.
|
||||
|
||||
[source,html]
|
||||
----
|
||||
<c:url value="/login" var="loginUrl"/>
|
||||
<form action="${loginUrl}" method="post"> <1>
|
||||
<c:if test="${param.error != null}"> <2>
|
||||
<p>
|
||||
Invalid username and password.
|
||||
</p>
|
||||
</c:if>
|
||||
<c:if test="${param.logout != null}"> <3>
|
||||
<p>
|
||||
You have been logged out.
|
||||
</p>
|
||||
</c:if>
|
||||
<p>
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username"/> <4>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password"/> <5>
|
||||
</p>
|
||||
<input type="hidden" <6>
|
||||
name="${_csrf.parameterName}"
|
||||
value="${_csrf.token}"/>
|
||||
<button type="submit" class="btn">Log in</button>
|
||||
</form>
|
||||
----
|
||||
|
||||
<1> A POST to the `/login` URL will attempt to authenticate the user
|
||||
<2> If the query parameter `error` exists, authentication was attempted and failed
|
||||
<3> If the query parameter `logout` exists, the user was successfully logged out
|
||||
<4> The username must be present as the HTTP parameter named __username__
|
||||
<5> The password must be present as the HTTP parameter named __password__
|
||||
<6> We must <<csrf-include-csrf-token>> To learn more read the <<csrf>> section of the reference
|
||||
|
||||
=== Form Login XML Configuration
|
||||
|
||||
[[ns-form-and-basic]]
|
||||
==== Form and Basic Login Options
|
||||
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs.
|
||||
In fact, since we didn't explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.
|
||||
However, the namespace offers plenty of support to allow you to customize these options.
|
||||
For example, if you want to supply your own login page, you could use:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<form-login login-page='/login.jsp'/>
|
||||
</http>
|
||||
----
|
||||
|
||||
Also note that we've added an extra `intercept-url` element to say that any requests for the login page should be available to anonymous users footnote:[See the chapter on pass:specialcharacters,macros[<<anonymous>>]] and also the <<authz-authenticated-voter,AuthenticatedVoter>> class for more details on how the value `IS_AUTHENTICATED_ANONYMOUSLY` is processed.].
|
||||
Otherwise the request would be matched by the pattern /** and it wouldn't be possible to access the login page itself!
|
||||
This is a common configuration error and will result in an infinite loop in the application.
|
||||
Spring Security will emit a warning in the log if your login page appears to be secured.
|
||||
It is also possible to have all requests matching a particular pattern bypass the security filter chain completely, by defining a separate `http` element for the pattern like this:
|
||||
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http pattern="/css/**" security="none"/>
|
||||
<http pattern="/login.jsp*" security="none"/>
|
||||
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<form-login login-page='/login.jsp'/>
|
||||
</http>
|
||||
----
|
||||
|
||||
From Spring Security 3.1 it is now possible to use multiple `http` elements to define separate security filter chain configurations for different request patterns.
|
||||
If the `pattern` attribute is omitted from an `http` element, it matches all requests.
|
||||
Creating an unsecured pattern is a simple example of this syntax, where the pattern is mapped to an empty filter chain footnote:[The use of multiple `<http>` elements is an important feature, allowing the namespace to simultaneously support both stateful and stateless paths within the same application, for example.
|
||||
The previous syntax, using the attribute `filters="none"` on an `intercept-url` element is incompatible with this change and is no longer supported in 3.1.].
|
||||
We'll look at this new syntax in more detail in the chapter on the <<filter-chains-with-ns,Security Filter Chain>>.
|
||||
|
||||
It's important to realise that these unsecured requests will be completely oblivious to any Spring Security web-related configuration or additional attributes such as `requires-channel`, so you will not be able to access information on the current user or call secured methods during the request.
|
||||
Use `access='IS_AUTHENTICATED_ANONYMOUSLY'` as an alternative if you still want the security filter chain to be applied.
|
||||
|
||||
If you want to use basic authentication instead of form login, then change the configuration to
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource.
|
||||
Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page.
|
@ -0,0 +1,18 @@
|
||||
[[jc-authentication-inmemory]]
|
||||
== In-Memory Authentication
|
||||
|
||||
We have already seen an example of configuring in-memory authentication for a single user.
|
||||
Below is an example to configure multiple users:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build());
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
|
||||
return manager;
|
||||
}
|
||||
----
|
@ -0,0 +1,44 @@
|
||||
[[jc-authentication]]
|
||||
= Authentication
|
||||
|
||||
include::in-memory.adoc[]
|
||||
|
||||
include::jdbc.adoc[]
|
||||
|
||||
include::ldap.adoc[]
|
||||
|
||||
include::authentication-provider.adoc[]
|
||||
|
||||
include::user-details-service.adoc[]
|
||||
|
||||
include::password-encoder.adoc[]
|
||||
|
||||
include::authentication-manager.adoc[]
|
||||
|
||||
include::session-management.adoc[]
|
||||
|
||||
include::rememberme.adoc[]
|
||||
|
||||
include::openid.adoc[]
|
||||
|
||||
include::anonymous.adoc[]
|
||||
|
||||
include::preauth.adoc[]
|
||||
|
||||
include::jaas.adoc[]
|
||||
|
||||
include::cas.adoc[]
|
||||
|
||||
include::x509.adoc[]
|
||||
|
||||
include::runas.adoc[]
|
||||
|
||||
include::form.adoc[]
|
||||
|
||||
include::basic.adoc[]
|
||||
|
||||
include::digest.adoc[]
|
||||
|
||||
include::logout.adoc[]
|
||||
|
||||
include::authentication-entry-point.adoc[]
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[jaas]]
|
||||
== Java Authentication and Authorization Service (JAAS) Provider
|
||||
|
@ -0,0 +1,24 @@
|
||||
[[jc-authentication-jdbc]]
|
||||
== JDBC Authentication
|
||||
|
||||
You can find the updates to support JDBC based authentication.
|
||||
The example below assumes that you have already defined a `DataSource` within your application.
|
||||
The https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig/jdbc[jdbc-javaconfig] sample provides a complete example of using JDBC based authentication.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource)
|
||||
.withDefaultSchema()
|
||||
.withUser(users.username("user").password("password").roles("USER"))
|
||||
.withUser(users.username("admin").password("password").roles("USER","ADMIN"));
|
||||
}
|
||||
----
|
@ -37,7 +37,7 @@ For full information on available configuration options, please consult the secu
|
||||
|
||||
|
||||
[[ldap-server]]
|
||||
=== Configuring an LDAP Server
|
||||
== Configuring an LDAP Server
|
||||
The first thing you need to do is configure the server against which authentication should take place.
|
||||
This is done using the `<ldap-server>` element from the security namespace.
|
||||
This can be configured to point at an external LDAP server, using the `url` attribute:
|
||||
@ -49,7 +49,7 @@ This can be configured to point at an external LDAP server, using the `url` attr
|
||||
|
||||
NOTE: `spring-security` provides integration with `apacheds` and `unboundid` as a embedded ldap servers. You can choose between them using the attribute `mode` in `ldap-server`.
|
||||
|
||||
==== Using an Embedded Test Server
|
||||
=== Using an Embedded Test Server
|
||||
The `<ldap-server>` element can also be used to create an embedded server, which can be very useful for testing and demonstrations.
|
||||
In this case you use it without the `url` attribute:
|
||||
|
||||
@ -73,7 +73,7 @@ Using plain Spring Beans the configuration would be much more cluttered.
|
||||
You must have the necessary Apache Directory dependency jars available for your application to use.
|
||||
These can be obtained from the LDAP sample application.
|
||||
|
||||
==== Using Bind Authentication
|
||||
=== Using Bind Authentication
|
||||
This is the most common LDAP authentication scenario.
|
||||
|
||||
[source,xml]
|
||||
@ -95,7 +95,7 @@ If used with the server definition above, this would perform a search under the
|
||||
Again the user login name is substituted for the parameter in the filter name, so it will search for an entry with the `uid` attribute equal to the user name.
|
||||
If `user-search-base` isn't supplied, the search will be performed from the root.
|
||||
|
||||
==== Loading Authorities
|
||||
=== Loading Authorities
|
||||
How authorities are loaded from groups in the LDAP directory is controlled by the following attributes.
|
||||
|
||||
* `group-search-base`.
|
||||
@ -123,7 +123,7 @@ 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
|
||||
== 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.
|
||||
@ -133,7 +133,7 @@ The main LDAP provider class, `LdapAuthenticationProvider`, doesn't actually do
|
||||
|
||||
|
||||
[[ldap-ldap-authenticators]]
|
||||
==== LdapAuthenticator Implementations
|
||||
=== LdapAuthenticator Implementations
|
||||
The authenticator is also responsible for retrieving any required user attributes.
|
||||
This is because the permissions on the attributes may depend on the type of authentication being used.
|
||||
For example, if binding as the user, it may be necessary to read them with the user's own permissions.
|
||||
@ -146,7 +146,7 @@ There are currently two authentication strategies supplied with Spring Security:
|
||||
This can either be done by retrieving the value of the password attribute and checking it locally or by performing an LDAP "compare" operation, where the supplied password is passed to the server for comparison and the real password value is never retrieved.
|
||||
|
||||
[[ldap-ldap-authenticators-common]]
|
||||
===== Common Functionality
|
||||
==== 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}`.
|
||||
@ -158,18 +158,18 @@ A combination of the two approaches can also be used - the patterns will be chec
|
||||
|
||||
|
||||
[[ldap-ldap-authenticators-bind]]
|
||||
===== BindAuthenticator
|
||||
==== BindAuthenticator
|
||||
The class `BindAuthenticator` in the package `org.springframework.security.ldap.authentication` implements the bind authentication strategy.
|
||||
It simply attempts to bind as the user.
|
||||
|
||||
|
||||
[[ldap-ldap-authenticators-password]]
|
||||
===== PasswordComparisonAuthenticator
|
||||
==== PasswordComparisonAuthenticator
|
||||
The class `PasswordComparisonAuthenticator` implements the password comparison authentication strategy.
|
||||
|
||||
|
||||
[[ldap-context-source]]
|
||||
==== Connecting to the LDAP Server
|
||||
=== Connecting to the LDAP Server
|
||||
The beans discussed above have to be able to connect to the server.
|
||||
They both have to be supplied with a `SpringSecurityContextSource` which is an extension of Spring LDAP's `ContextSource`.
|
||||
Unless you have special requirements, you will usually configure a `DefaultSpringSecurityContextSource` bean, which can be configured with the URL of your LDAP server and optionally with the username and password of a "manager" user which will be used by default when binding to the server (instead of binding anonymously).
|
||||
@ -177,14 +177,14 @@ For more information read the Javadoc for this class and for Spring LDAP's `Abst
|
||||
|
||||
|
||||
[[ldap-searchobjects]]
|
||||
==== LDAP Search Objects
|
||||
=== LDAP Search Objects
|
||||
Often a more complicated strategy than simple DN-matching is required to locate a user entry in the directory.
|
||||
This can be encapsulated in an `LdapUserSearch` instance which can be supplied to the authenticator implementations, for example, to allow them to locate a user.
|
||||
The supplied implementation is `FilterBasedLdapUserSearch`.
|
||||
|
||||
|
||||
[[ldap-searchobjects-filter]]
|
||||
===== FilterBasedLdapUserSearch
|
||||
==== FilterBasedLdapUserSearch
|
||||
This bean uses an LDAP filter to match the user object in the directory.
|
||||
The process is explained in the Javadoc for the corresponding search method on the https://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name%2C%2520java.lang.String%2C%2520java.lang.Object%5B%5D%2C%2520javax.naming.directory.SearchControls)[JDK DirContext class].
|
||||
As explained there, the search filter can be supplied with parameters.
|
||||
@ -192,7 +192,7 @@ For this class, the only valid parameter is `{0}` which will be replaced with th
|
||||
|
||||
|
||||
[[ldap-authorities]]
|
||||
==== LdapAuthoritiesPopulator
|
||||
=== LdapAuthoritiesPopulator
|
||||
After authenticating the user successfully, the `LdapAuthenticationProvider` will attempt to load a set of authorities for the user by calling the configured `LdapAuthoritiesPopulator` bean.
|
||||
The `DefaultLdapAuthoritiesPopulator` is an implementation which will load the authorities by searching the directory for groups of which the user is a member (typically these will be `groupOfNames` or `groupOfUniqueNames` entries in the directory).
|
||||
Consult the Javadoc for this class for more details on how it works.
|
||||
@ -200,7 +200,7 @@ Consult the Javadoc for this class for more details on how it works.
|
||||
If you want to use LDAP only for authentication, but load the authorities from a difference source (such as a database) then you can provide your own implementation of this interface and inject that instead.
|
||||
|
||||
[[ldap-bean-config]]
|
||||
==== Spring Bean Configuration
|
||||
=== Spring Bean Configuration
|
||||
A typical configuration, using some of the beans we've discussed here, might look like this:
|
||||
|
||||
[source,xml]
|
||||
@ -255,7 +255,7 @@ The authenticator would then call the search object to obtain the correct user's
|
||||
|
||||
|
||||
[[ldap-custom-user-details]]
|
||||
==== LDAP Attributes and Customized UserDetails
|
||||
=== LDAP Attributes and Customized UserDetails
|
||||
The net result of an authentication using `LdapAuthenticationProvider` is the same as a normal Spring Security authentication using the standard `UserDetailsService` interface.
|
||||
A `UserDetails` object is created and stored in the returned `Authentication` object.
|
||||
As with using a `UserDetailsService`, a common requirement is to be able to customize this implementation and add extra properties.
|
||||
@ -283,13 +283,13 @@ With the `BindAuthenticator`, the context returned from the bind operation will
|
||||
|
||||
|
||||
[[ldap-active-directory]]
|
||||
=== Active Directory Authentication
|
||||
== Active Directory Authentication
|
||||
Active Directory supports its own non-standard authentication options, and the normal usage pattern doesn't fit too cleanly with the standard `LdapAuthenticationProvider`.
|
||||
Typically authentication is performed using the domain username (in the form `user@domain`), rather than using an LDAP distinguished name.
|
||||
To make this easier, Spring Security 3.1 has an authentication provider which is customized for a typical Active Directory setup.
|
||||
|
||||
|
||||
==== ActiveDirectoryLdapAuthenticationProvider
|
||||
=== ActiveDirectoryLdapAuthenticationProvider
|
||||
Configuring `ActiveDirectoryLdapAuthenticationProvider` is quite straightforward.
|
||||
You just need to supply the domain name and an LDAP URL supplying the address of the server footnote:[It is also possible to obtain the server's IP address using a DNS lookup.
|
||||
This is not currently supported, but hopefully will be in a future version.].
|
||||
@ -315,7 +315,74 @@ By default, the user authorities are obtained from the `memberOf` attribute valu
|
||||
The authorities allocated to the user can again be customized using a `UserDetailsContextMapper`.
|
||||
You can also inject a `GrantedAuthoritiesMapper` into the provider instance to control the authorities which end up in the `Authentication` object.
|
||||
|
||||
===== Active Directory Error Codes
|
||||
==== Active Directory Error Codes
|
||||
By default, a failed result will cause a standard Spring Security `BadCredentialsException`.
|
||||
If you set the property `convertSubErrorCodesToExceptions` to `true`, the exception messages will be parsed to attempt to extract the Active Directory-specific error code and raise a more specific exception.
|
||||
Check the class Javadoc for more information.
|
||||
|
||||
== LDAP Java Configuration
|
||||
|
||||
You can find the updates to support LDAP based authentication.
|
||||
The https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig/ldap[ldap-javaconfig] sample provides a complete example of using LDAP based authentication.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchBase("ou=groups");
|
||||
}
|
||||
----
|
||||
|
||||
The example above uses the following LDIF and an embedded Apache DS LDAP instance.
|
||||
|
||||
.users.ldif
|
||||
----
|
||||
dn: ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: groups
|
||||
|
||||
dn: ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: people
|
||||
|
||||
dn: uid=admin,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Rod Johnson
|
||||
sn: Johnson
|
||||
uid: admin
|
||||
userPassword: password
|
||||
|
||||
dn: uid=user,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Dianne Emu
|
||||
sn: Emu
|
||||
uid: user
|
||||
userPassword: password
|
||||
|
||||
dn: cn=user,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: user
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
uniqueMember: uid=user,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=admin,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: admin
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
----
|
@ -0,0 +1,128 @@
|
||||
[[jc-logout]]
|
||||
== Handling Logouts
|
||||
|
||||
[[logout-java-configuration]]
|
||||
=== Logout Java Configuration
|
||||
|
||||
When using the `{security-api-url}org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html[WebSecurityConfigurerAdapter]`, logout capabilities are automatically applied.
|
||||
The default is that accessing the URL `/logout` will log the user out by:
|
||||
|
||||
- Invalidating the HTTP Session
|
||||
- Cleaning up any RememberMe authentication that was configured
|
||||
- Clearing the `SecurityContextHolder`
|
||||
- Redirect to `/login?logout`
|
||||
|
||||
Similar to configuring login capabilities, however, you also have various options to further customize your logout requirements:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.logout(logout -> // <1>
|
||||
logout
|
||||
.logoutUrl("/my/logout") // <2>
|
||||
.logoutSuccessUrl("/my/index") // <3>
|
||||
.logoutSuccessHandler(logoutSuccessHandler) // <4>
|
||||
.invalidateHttpSession(true) // <5>
|
||||
.addLogoutHandler(logoutHandler) // <6>
|
||||
.deleteCookies(cookieNamesToClear) // <7>
|
||||
)
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
<1> Provides logout support.
|
||||
This is automatically applied when using `WebSecurityConfigurerAdapter`.
|
||||
<2> The URL that triggers log out to occur (default is `/logout`).
|
||||
If CSRF protection is enabled (default), then the request must also be a POST.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutUrl-java.lang.String-[JavaDoc].
|
||||
<3> The URL to redirect to after logout has occurred.
|
||||
The default is `/login?logout`.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutSuccessUrl-java.lang.String-[JavaDoc].
|
||||
<4> Let's you specify a custom `LogoutSuccessHandler`.
|
||||
If this is specified, `logoutSuccessUrl()` is ignored.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutSuccessHandler-org.springframework.security.web.authentication.logout.LogoutSuccessHandler-[JavaDoc].
|
||||
<5> Specify whether to invalidate the `HttpSession` at the time of logout.
|
||||
This is *true* by default.
|
||||
Configures the `SecurityContextLogoutHandler` under the covers.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#invalidateHttpSession-boolean-[JavaDoc].
|
||||
<6> Adds a `LogoutHandler`.
|
||||
`SecurityContextLogoutHandler` is added as the last `LogoutHandler` by default.
|
||||
<7> Allows specifying the names of cookies to be removed on logout success.
|
||||
This is a shortcut for adding a `CookieClearingLogoutHandler` explicitly.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
Logouts can of course also be configured using the XML Namespace notation.
|
||||
Please see the documentation for the <<nsa-logout, logout element>> in the Spring Security XML Namespace section for further details.
|
||||
===
|
||||
|
||||
Generally, in order to customize logout functionality, you can add
|
||||
`{security-api-url}org/springframework/security/web/authentication/logout/LogoutHandler.html[LogoutHandler]`
|
||||
and/or
|
||||
`{security-api-url}org/springframework/security/web/authentication/logout/LogoutSuccessHandler.html[LogoutSuccessHandler]`
|
||||
implementations.
|
||||
For many common scenarios, these handlers are applied under the
|
||||
covers when using the fluent API.
|
||||
|
||||
[[ns-logout]]
|
||||
=== Logout XML Configuration
|
||||
The `logout` element adds support for logging out by navigating to a particular URL.
|
||||
The default logout URL is `/logout`, but you can set it to something else using the `logout-url` attribute.
|
||||
More information on other available attributes may be found in the namespace appendix.
|
||||
|
||||
[[jc-logout-handler]]
|
||||
=== LogoutHandler
|
||||
|
||||
Generally, `{security-api-url}org/springframework/security/web/authentication/logout/LogoutHandler.html[LogoutHandler]`
|
||||
implementations indicate classes that are able to participate in logout handling.
|
||||
They are expected to be invoked to perform necessary clean-up.
|
||||
As such they should
|
||||
not throw exceptions.
|
||||
Various implementations are provided:
|
||||
|
||||
- {security-api-url}org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.html[PersistentTokenBasedRememberMeServices]
|
||||
- {security-api-url}org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.html[TokenBasedRememberMeServices]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/CookieClearingLogoutHandler.html[CookieClearingLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/csrf/CsrfLogoutHandler.html[CsrfLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.html[SecurityContextLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/HeaderWriterLogoutHandler.html[HeaderWriterLogoutHandler]
|
||||
|
||||
Please see <<remember-me-impls>> for details.
|
||||
|
||||
Instead of providing `LogoutHandler` implementations directly, the fluent API also provides shortcuts that provide the respective `LogoutHandler` implementations under the covers.
|
||||
E.g. `deleteCookies()` allows specifying the names of one or more cookies to be removed on logout success.
|
||||
This is a shortcut compared to adding a `CookieClearingLogoutHandler`.
|
||||
|
||||
[[jc-logout-success-handler]]
|
||||
=== LogoutSuccessHandler
|
||||
|
||||
The `LogoutSuccessHandler` is called after a successful logout by the `LogoutFilter`, to handle e.g.
|
||||
redirection or forwarding to the appropriate destination.
|
||||
Note that the interface is almost the same as the `LogoutHandler` but may raise an exception.
|
||||
|
||||
The following implementations are provided:
|
||||
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/SimpleUrlLogoutSuccessHandler.html[SimpleUrlLogoutSuccessHandler]
|
||||
- HttpStatusReturningLogoutSuccessHandler
|
||||
|
||||
As mentioned above, you don't need to specify the `SimpleUrlLogoutSuccessHandler` directly.
|
||||
Instead, the fluent API provides a shortcut by setting the `logoutSuccessUrl()`.
|
||||
This will setup the `SimpleUrlLogoutSuccessHandler` under the covers.
|
||||
The provided URL will be redirected to after a logout has occurred.
|
||||
The default is `/login?logout`.
|
||||
|
||||
The `HttpStatusReturningLogoutSuccessHandler` can be interesting in REST API type scenarios.
|
||||
Instead of redirecting to a URL upon the successful logout, this `LogoutSuccessHandler` allows you to provide a plain HTTP status code to be returned.
|
||||
If not configured a status code 200 will be returned by default.
|
||||
|
||||
[[jc-logout-references]]
|
||||
=== Further Logout-Related References
|
||||
|
||||
- <<ns-logout, Logout Handling>>
|
||||
- <<test-logout, Testing Logout>>
|
||||
- <<servletapi-logout, HttpServletRequest.logout()>>
|
||||
- <<remember-me-impls>>
|
||||
- <<csrf-logout, Logging Out>> in section CSRF Caveats
|
||||
- Section <<cas-singlelogout, Single Logout>> (CAS protocol)
|
||||
- Documentation for the <<nsa-logout, logout element>> in the Spring Security XML Namespace section
|
@ -0,0 +1,58 @@
|
||||
[[ns-openid]]
|
||||
== OpenID Support
|
||||
The namespace supports https://openid.net/[OpenID] login either instead of, or in addition to normal form-based login, with a simple change:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<openid-login />
|
||||
</http>
|
||||
----
|
||||
|
||||
You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory `<user-service>`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<user name="https://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
|
||||
----
|
||||
|
||||
You should be able to login using the `myopenid.com` site to authenticate.
|
||||
It is also possible to select a specific `UserDetailsService` bean for use OpenID by setting the `user-service-ref` attribute on the `openid-login` element.
|
||||
See the previous section on <<ns-auth-providers,authentication providers>> for more information.
|
||||
Note that we have omitted the password attribute from the above user configuration, since this set of user data is only being used to load the authorities for the user.
|
||||
A random password will be generated internally, preventing you from accidentally using this user data as an authentication source elsewhere in your configuration.
|
||||
|
||||
|
||||
=== Attribute Exchange
|
||||
Support for OpenID https://openid.net/specs/openid-attribute-exchange-1_0.html[attribute exchange].
|
||||
As an example, the following configuration would attempt to retrieve the email and full name from the OpenID provider, for use by the application:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<openid-login>
|
||||
<attribute-exchange>
|
||||
<openid-attribute name="email" type="https://axschema.org/contact/email" required="true"/>
|
||||
<openid-attribute name="name" type="https://axschema.org/namePerson"/>
|
||||
</attribute-exchange>
|
||||
</openid-login>
|
||||
----
|
||||
|
||||
The "type" of each OpenID attribute is a URI, determined by a particular schema, in this case https://axschema.org/[https://axschema.org/].
|
||||
If an attribute must be retrieved for successful authentication, the `required` attribute can be set.
|
||||
The exact schema and attributes supported will depend on your OpenID provider.
|
||||
The attribute values are returned as part of the authentication process and can be accessed afterwards using the following code:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
OpenIDAuthenticationToken token =
|
||||
(OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
|
||||
List<OpenIDAttribute> attributes = token.getAttributes();
|
||||
----
|
||||
|
||||
The `OpenIDAttribute` contains the attribute type and the retrieved value (or values in the case of multi-valued attributes).
|
||||
We'll see more about how the `SecurityContextHolder` class is used when we look at core Spring Security components in the <<core-components,technical overview>> chapter.
|
||||
Multiple attribute exchange configurations are also be supported, if you wish to use multiple identity providers.
|
||||
You can supply multiple `attribute-exchange` elements, using an `identifier-matcher` attribute on each.
|
||||
This contains a regular expression which will be matched against the OpenID identifier supplied by the user.
|
||||
See the OpenID sample application in the codebase for an example configuration, providing different attribute lists for the Google, Yahoo and MyOpenID providers.
|
@ -1,12 +1,12 @@
|
||||
[[core-services-password-encoding]]
|
||||
= Password Encoding
|
||||
== Password Encoding
|
||||
|
||||
Spring Security's `PasswordEncoder` interface is used to perform a one way transformation of a password to allow the password to be stored securely.
|
||||
Given `PasswordEncoder` is a one way transformation, it is not intended when the password transformation needs to be two way (i.e. storing credentials used to authenticate to a database).
|
||||
Typically `PasswordEncoder` is used for storing a password that needs to be compared to a user provided password at the time of authentication.
|
||||
|
||||
[[pe-history]]
|
||||
== Password History
|
||||
=== Password History
|
||||
|
||||
Throughout the years the standard mechanism for storing passwords has evolved.
|
||||
In the beginning passwords were stored in plain text.
|
||||
@ -52,7 +52,7 @@ The short term credential can be validated quickly without any loss in security.
|
||||
|
||||
|
||||
[[pe-dpe]]
|
||||
== DelegatingPasswordEncoder
|
||||
=== DelegatingPasswordEncoder
|
||||
|
||||
Prior to Spring Security 5.0 the default `PasswordEncoder` was `NoOpPasswordEncoder` which required plain text passwords.
|
||||
Based upon the <<password-history,Password History>> section you might expect that the default `PasswordEncoder` is now something like `BCryptPasswordEncoder`.
|
||||
@ -93,7 +93,7 @@ PasswordEncoder passwordEncoder =
|
||||
----
|
||||
|
||||
[[pe-dpe-format]]
|
||||
=== Password Storage Format
|
||||
==== Password Storage Format
|
||||
|
||||
The general format for a password is:
|
||||
|
||||
@ -137,7 +137,7 @@ Additionally, most formats are easy for an attacker to figure out without the pr
|
||||
For example, BCrypt passwords often start with `$2a$`.
|
||||
====
|
||||
|
||||
=== Password Encoding
|
||||
==== Password Encoding
|
||||
|
||||
The `idForEncode` passed into the constructor determines which `PasswordEncoder` will be used for encoding passwords.
|
||||
In the `DelegatingPasswordEncoder` we constructed above, that means that the result of encoding `password` would be delegated to `BCryptPasswordEncoder` and be prefixed with `{bcrypt}`.
|
||||
@ -148,7 +148,7 @@ The end result would look like:
|
||||
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
|
||||
----
|
||||
|
||||
=== Password Matching
|
||||
==== Password Matching
|
||||
|
||||
Matching is done based upon the `{id}` and the mapping of the `id` to the `PasswordEncoder` provided in the constructor.
|
||||
Our example in <<Password Storage Format>> provides a working example of how this is done.
|
||||
@ -160,7 +160,7 @@ This is important, because unlike encryption, password hashes are designed so th
|
||||
Since there is no way to recover the plaintext, it makes it difficult to migrate the passwords.
|
||||
While it is simple for users to migrate `NoOpPasswordEncoder`, we chose to include it by default to make it simple for the getting started experience.
|
||||
|
||||
=== Getting Started Experience
|
||||
==== Getting Started Experience
|
||||
|
||||
If you are putting together a demo or a sample, it is a bit cumbersome to take time to hash the passwords of your users.
|
||||
There are convenience mechanisms to make this easier, but this is still not intended for production.
|
||||
@ -197,7 +197,7 @@ This does hash the password that is stored, but the passwords are still exposed
|
||||
Therefore, it is still not considered secure for a production environment.
|
||||
For production, you should hash your passwords externally.
|
||||
|
||||
=== Troubleshooting
|
||||
==== Troubleshooting
|
||||
|
||||
The following error occurs when one of the passwords that are stored has no id as described in <<pe-dpe-format>>.
|
||||
|
||||
@ -251,7 +251,7 @@ For a complete listing of the mappings refer to the Javadoc on
|
||||
https://docs.spring.io/spring-security/site/docs/5.0.x/api/org/springframework/security/crypto/factory/PasswordEncoderFactories.html[PasswordEncoderFactories].
|
||||
|
||||
[[pe-bcpe]]
|
||||
== BCryptPasswordEncoder
|
||||
=== BCryptPasswordEncoder
|
||||
|
||||
The `BCryptPasswordEncoder` implementation uses the widely supported https://en.wikipedia.org/wiki/Bcrypt[bcrypt] algorithm to hash the passwords.
|
||||
In order to make it more resistent to password cracking, bcrypt is deliberately slow.
|
||||
@ -266,7 +266,7 @@ assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
[[pe-a2pe]]
|
||||
== Argon2PasswordEncoder
|
||||
=== Argon2PasswordEncoder
|
||||
|
||||
The `Argon2PasswordEncoder` implementation uses the https://en.wikipedia.org/wiki/Argon2[Argon2] algorithm to hash the passwords.
|
||||
Argon2 is the winner of the https://en.wikipedia.org/wiki/Password_Hashing_Competition[Password Hashing Competition].
|
||||
@ -283,7 +283,7 @@ assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
[[pe-pbkdf2pe]]
|
||||
== Pbkdf2PasswordEncoder
|
||||
=== Pbkdf2PasswordEncoder
|
||||
|
||||
The `Pbkdf2PasswordEncoder` implementation uses the https://en.wikipedia.org/wiki/PBKDF2[PBKDF2] algorithm to hash the passwords.
|
||||
In order to defeat password cracking PBKDF2 is a deliberately slow algorithm.
|
||||
@ -299,7 +299,7 @@ assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
[[pe-scpe]]
|
||||
== SCryptPasswordEncoder
|
||||
=== SCryptPasswordEncoder
|
||||
|
||||
The `SCryptPasswordEncoder` implementation uses https://en.wikipedia.org/wiki/Scrypt[scrypt] algorithm to hash the passwords.
|
||||
In order to defeat password cracking on custom hardware scrypt is a deliberately slow algorithm that requires large amounts of memory.
|
||||
@ -313,8 +313,38 @@ String result = encoder.encode("myPassword");
|
||||
assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
== Other PasswordEncoders
|
||||
=== Other PasswordEncoders
|
||||
|
||||
There are a significant number of other `PasswordEncoder` implementations that exist entirely for backward compatibility.
|
||||
They are all deprecated to indicate that they are no longer considered secure.
|
||||
However, there are no plans to remove them since it is difficult to migrate existing legacy systems.
|
||||
|
||||
[[ns-password-encoder]]
|
||||
=== Password Encoder XML Configuration
|
||||
Passwords should always be encoded using a secure hashing algorithm designed for the purpose (not a standard algorithm like SHA or MD5).
|
||||
This is supported by the `<password-encoder>` element.
|
||||
With bcrypt encoded passwords, the original authentication provider configuration would look like this:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans:bean name="bcryptEncoder"
|
||||
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<password-encoder ref="bcryptEncoder"/>
|
||||
<user-service>
|
||||
<user name="jimi" password="$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
|
||||
authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
|
||||
authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
|
||||
|
||||
bcrypt is a good choice for most cases, unless you have a legacy system which forces you to use a different algorithm.
|
||||
If you are using a simple hashing algorithm or, even worse, storing plain text passwords, then you should consider migrating to a more secure option like bcrypt.
|
@ -1,6 +1,5 @@
|
||||
|
||||
|
||||
[[remember-me]]
|
||||
[[ns-remember-me]]
|
||||
== Remember-Me Authentication
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[runas]]
|
||||
== Run-As Authentication Replacement
|
||||
|
@ -1,9 +1,119 @@
|
||||
|
||||
[[session-mgmt]]
|
||||
[[ns-session-mgmt]]
|
||||
== Session Management
|
||||
HTTP session related functionality is handled by a combination of the `SessionManagementFilter` and the `SessionAuthenticationStrategy` interface, which the filter delegates to.
|
||||
Typical usage includes session-fixation protection attack prevention, detection of session timeouts and restrictions on how many sessions an authenticated user may have open concurrently.
|
||||
|
||||
=== Detecting Timeouts
|
||||
You can configure Spring Security to detect the submission of an invalid session ID and redirect the user to an appropriate URL.
|
||||
This is achieved through the `session-management` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management invalid-session-url="/invalidSession.htm" />
|
||||
</http>
|
||||
----
|
||||
|
||||
Note that if you use this mechanism to detect session timeouts, it may falsely report an error if the user logs out and then logs back in without closing the browser.
|
||||
This is because the session cookie is not cleared when you invalidate the session and will be resubmitted even if the user has logged out.
|
||||
You may be able to explicitly delete the JSESSIONID cookie on logging out, for example by using the following syntax in the logout handler:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<logout delete-cookies="JSESSIONID" />
|
||||
</http>
|
||||
----
|
||||
|
||||
Unfortunately this can't be guaranteed to work with every servlet container, so you will need to test it in your environment
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
If you are running your application behind a proxy, you may also be able to remove the session cookie by configuring the proxy server.
|
||||
For example, using Apache HTTPD's mod_headers, the following directive would delete the `JSESSIONID` cookie by expiring it in the response to a logout request (assuming the application is deployed under the path `/tutorial`):
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<LocationMatch "/tutorial/logout">
|
||||
Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
|
||||
</LocationMatch>
|
||||
----
|
||||
===
|
||||
|
||||
|
||||
[[ns-concurrent-sessions]]
|
||||
=== Concurrent Session Control
|
||||
If you wish to place constraints on a single user's ability to log in to your application, Spring Security supports this out of the box with the following simple additions.
|
||||
First you need to add the following listener to your `web.xml` file to keep Spring Security updated about session lifecycle events:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.springframework.security.web.session.HttpSessionEventPublisher
|
||||
</listener-class>
|
||||
</listener>
|
||||
----
|
||||
|
||||
Then add the following lines to your application context:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management>
|
||||
<concurrency-control max-sessions="1" />
|
||||
</session-management>
|
||||
</http>
|
||||
----
|
||||
|
||||
This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated.
|
||||
Often you would prefer to prevent a second login, in which case you can use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management>
|
||||
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
|
||||
</session-management>
|
||||
</http>
|
||||
----
|
||||
|
||||
The second login will then be rejected.
|
||||
By "rejected", we mean that the user will be sent to the `authentication-failure-url` if form-based login is being used.
|
||||
If the second authentication takes place through another non-interactive mechanism, such as "remember-me", an "unauthorized" (401) error will be sent to the client.
|
||||
If instead you want to use an error page, you can add the attribute `session-authentication-error-url` to the `session-management` element.
|
||||
|
||||
If you are using a customized authentication filter for form-based login, then you have to configure concurrent session control support explicitly.
|
||||
More details can be found in the <<session-mgmt,Session Management chapter>>.
|
||||
|
||||
[[ns-session-fixation]]
|
||||
=== Session Fixation Attack Protection
|
||||
https://en.wikipedia.org/wiki/Session_fixation[Session fixation] attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example).
|
||||
Spring Security protects against this automatically by creating a new session or otherwise changing the session ID when a user logs in.
|
||||
If you don't require this protection, or it conflicts with some other requirement, you can control the behavior using the `session-fixation-protection` attribute on `<session-management>`, which has four options
|
||||
|
||||
* `none` - Don't do anything.
|
||||
The original session will be retained.
|
||||
|
||||
* `newSession` - Create a new "clean" session, without copying the existing session data (Spring Security-related attributes will still be copied).
|
||||
|
||||
* `migrateSession` - Create a new session and copy all existing session attributes to the new session.
|
||||
This is the default in Servlet 3.0 or older containers.
|
||||
|
||||
* `changeSessionId` - Do not create a new session.
|
||||
Instead, use the session fixation protection provided by the Servlet container (`HttpServletRequest#changeSessionId()`).
|
||||
This option is only available in Servlet 3.1 (Java EE 7) and newer containers.
|
||||
Specifying it in older containers will result in an exception.
|
||||
This is the default in Servlet 3.1 and newer containers.
|
||||
|
||||
|
||||
When session fixation protection occurs, it results in a `SessionFixationProtectionEvent` being published in the application context.
|
||||
If you use `changeSessionId`, this protection will __also__ result in any `javax.servlet.http.HttpSessionIdListener` s being notified, so use caution if your code listens for both events.
|
||||
See the <<session-mgmt,Session Management>> chapter for additional information.
|
||||
|
||||
=== 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:[
|
@ -0,0 +1,26 @@
|
||||
[[jc-authentication-userdetailsservice]]
|
||||
== UserDetailsService
|
||||
|
||||
You can define custom authentication by exposing a custom `UserDetailsService` as a bean.
|
||||
For example, the following will customize authentication assuming that `SpringDataUserDetailsService` implements `UserDetailsService`:
|
||||
|
||||
NOTE: This is only used if the `AuthenticationManagerBuilder` has not been populated and no `AuthenticationProviderBean` is defined.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public SpringDataUserDetailsService springDataUserDetailsService() {
|
||||
return new SpringDataUserDetailsService();
|
||||
}
|
||||
----
|
||||
|
||||
You can also customize how passwords are encoded by exposing a `PasswordEncoder` as a bean.
|
||||
For example, if you use bcrypt you can add a bean definition as shown below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
----
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[x509]]
|
||||
== X.509 Authentication
|
||||
|
@ -0,0 +1,30 @@
|
||||
[[jc-authorize-requests]]
|
||||
== Authorize Requests
|
||||
Our examples have only required users to be authenticated and have done so for every URL in our application.
|
||||
We can specify custom requirements for our URLs by adding multiple children to our `http.authorizeRequests()` method.
|
||||
For example:
|
||||
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests -> // <1>
|
||||
authorizeRequests
|
||||
.antMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
|
||||
.antMatchers("/admin/**").hasRole("ADMIN") // <3>
|
||||
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
|
||||
.anyRequest().authenticated() // <5>
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
}
|
||||
----
|
||||
|
||||
<1> There are multiple children to the `http.authorizeRequests()` method each matcher is considered in the order they were declared.
|
||||
<2> We specified multiple URL patterns that any user can access.
|
||||
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
|
||||
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
|
||||
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
|
||||
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
|
||||
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
|
||||
<5> Any URL that has not already been matched on only requires that the user be authenticated
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[authorization]]
|
||||
= Authorization
|
||||
The advanced authorization capabilities within Spring Security represent one of the most compelling reasons for its popularity.
|
||||
@ -13,3 +12,9 @@ include::secure-objects.adoc[]
|
||||
|
||||
include::expression-based.adoc[]
|
||||
|
||||
include::authorize-requests.adoc[]
|
||||
|
||||
include::method-security.adoc[]
|
||||
|
||||
include::acls.adoc[]
|
||||
|
||||
|
@ -0,0 +1,192 @@
|
||||
[[jc-method]]
|
||||
== Method Security
|
||||
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods.
|
||||
It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation.
|
||||
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
|
||||
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
=== EnableGlobalMethodSecurity
|
||||
|
||||
We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.
|
||||
For example, the following would enable Spring Security's `@Secured` annotation.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
|
||||
Spring Security's native annotation support defines a set of attributes for the method.
|
||||
These will be passed to the AccessDecisionManager for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@Secured("ROLE_TELLER")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Support for JSR-250 annotations can be enabled using
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations.
|
||||
To use the new expression-based syntax, you would use
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
and the equivalent Java code would be
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@PreAuthorize("hasAuthority('ROLE_TELLER')")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
=== GlobalMethodSecurityConfiguration
|
||||
|
||||
Sometimes you may need to perform operations that are more complicated than are possible with the `@EnableGlobalMethodSecurity` annotation allow.
|
||||
For these instances, you can extend the `GlobalMethodSecurityConfiguration` ensuring that the `@EnableGlobalMethodSecurity` annotation is present on your subclass.
|
||||
For example, if you wanted to provide a custom `MethodSecurityExpressionHandler`, you could use the following configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
// ... create and return custom MethodSecurityExpressionHandler ...
|
||||
return expressionHandler;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
For additional information about methods that can be overridden, refer to the `GlobalMethodSecurityConfiguration` Javadoc.
|
||||
|
||||
[[ns-global-method]]
|
||||
=== The <global-method-security> Element
|
||||
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context.
|
||||
You should only declare one `<global-method-security>` element.
|
||||
The following declaration would enable support for Spring Security's `@Secured`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security secured-annotations="enabled" />
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly.
|
||||
Spring Security's native annotation support defines a set of attributes for the method.
|
||||
These will be passed to the `AccessDecisionManager` for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@Secured("ROLE_TELLER")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Support for JSR-250 annotations can be enabled using
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security jsr250-annotations="enabled" />
|
||||
----
|
||||
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations.
|
||||
To use the new expression-based syntax, you would use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security pre-post-annotations="enabled" />
|
||||
----
|
||||
|
||||
and the equivalent Java code would be
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@PreAuthorize("hasAuthority('ROLE_TELLER')")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Expression-based annotations are a good choice if you need to define simple rules that go beyond checking the role names against the user's list of authorities.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
The annotated methods will only be secured for instances which are defined as Spring beans (in the same application context in which method-security is enabled).
|
||||
If you want to secure instances which are not created by Spring (using the `new` operator, for example) then you need to use AspectJ.
|
||||
===
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behaviour will not be well-defined otherwise.
|
||||
If two annotations are found which apply to a particular method, then only one of them will be applied.
|
||||
===
|
||||
|
||||
[[ns-protect-pointcut]]
|
||||
=== Adding Security Pointcuts using protect-pointcut
|
||||
|
||||
The use of `protect-pointcut` is particularly powerful, as it allows you to apply security to many beans with only a simple declaration.
|
||||
Consider the following example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security>
|
||||
<protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"
|
||||
access="ROLE_USER"/>
|
||||
</global-method-security>
|
||||
----
|
||||
|
||||
This will protect all methods on beans declared in the application context whose classes are in the `com.mycompany` package and whose class names end in "Service".
|
||||
Only users with the `ROLE_USER` role will be able to invoke these methods.
|
||||
As with URL matching, the most specific matches must come first in the list of pointcuts, as the first matching expression will be used.
|
||||
Security annotations take precedence over pointcuts.
|
@ -1,22 +1,22 @@
|
||||
[[crypto]]
|
||||
== Spring Security Crypto Module
|
||||
= Spring Security Crypto Module
|
||||
|
||||
|
||||
[[spring-security-crypto-introduction]]
|
||||
=== Introduction
|
||||
== Introduction
|
||||
The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding.
|
||||
The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code.
|
||||
|
||||
|
||||
[[spring-security-crypto-encryption]]
|
||||
=== Encryptors
|
||||
== Encryptors
|
||||
The Encryptors class provides factory methods for constructing symmetric encryptors.
|
||||
Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form.
|
||||
You can also construct TextEncryptors to encrypt text strings.
|
||||
Encryptors are thread-safe.
|
||||
|
||||
[[spring-security-crypto-encryption-bytes]]
|
||||
==== BytesEncryptor
|
||||
=== BytesEncryptor
|
||||
Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor:
|
||||
|
||||
[source,java]
|
||||
@ -39,7 +39,7 @@ String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte
|
||||
----
|
||||
|
||||
[[spring-security-crypto-encryption-text]]
|
||||
==== TextEncryptor
|
||||
=== TextEncryptor
|
||||
Use the Encryptors.text factory method to construct a standard TextEncryptor:
|
||||
|
||||
[source,java]
|
||||
@ -65,13 +65,13 @@ This is less secure, but necessary for encrypted data that needs to be queried a
|
||||
An example of queryable encrypted text would be an OAuth apiKey.
|
||||
|
||||
[[spring-security-crypto-keygenerators]]
|
||||
=== Key Generators
|
||||
== Key Generators
|
||||
The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators.
|
||||
Using this class, you can create a BytesKeyGenerator to generate byte[] keys.
|
||||
You can also construct a StringKeyGenerator to generate string keys.
|
||||
KeyGenerators are thread-safe.
|
||||
|
||||
==== BytesKeyGenerator
|
||||
=== BytesKeyGenerator
|
||||
Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance:
|
||||
|
||||
[source,java]
|
||||
@ -95,7 +95,7 @@ Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator tha
|
||||
KeyGenerators.shared(16);
|
||||
----
|
||||
|
||||
==== StringKeyGenerator
|
||||
=== StringKeyGenerator
|
||||
Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String:
|
||||
|
||||
[source,java]
|
||||
@ -104,7 +104,7 @@ KeyGenerators.string();
|
||||
----
|
||||
|
||||
[[spring-security-crypto-passwordencoders]]
|
||||
=== Password Encoding
|
||||
== Password Encoding
|
||||
The password package of the spring-security-crypto module provides support for encoding passwords.
|
||||
`PasswordEncoder` is the central service interface and has the following signature:
|
||||
|
@ -0,0 +1,33 @@
|
||||
[[ns-requires-channel]]
|
||||
== HTTPS
|
||||
|
||||
=== Adding HTTP/HTTPS Channel Security
|
||||
If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the `requires-channel` attribute on `<intercept-url>`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
|
||||
...
|
||||
</http>
|
||||
----
|
||||
|
||||
With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL footnote:[For more details on how channel-processing is implemented, see the Javadoc for `ChannelProcessingFilter` and related classes.].
|
||||
The available options are "http", "https" or "any".
|
||||
Using the value "any" means that either HTTP or HTTPS can be used.
|
||||
|
||||
If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<port-mappings>
|
||||
<port-mapping http="9080" https="9443"/>
|
||||
</port-mappings>
|
||||
</http>
|
||||
----
|
||||
|
||||
Note that in order to be truly secure, an application should not use HTTP at all or switch between HTTP and HTTPS.
|
||||
It should start in HTTPS (with the user entering an HTTPS URL) and use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[csrf]]
|
||||
== Cross Site Request Forgery (CSRF)
|
||||
This section discusses Spring Security's https://en.wikipedia.org/wiki/Cross-site_request_forgery[ Cross Site Request Forgery (CSRF)] support.
|
@ -1,5 +1,5 @@
|
||||
|
||||
[[headers]]
|
||||
[[ns-headers]]
|
||||
== Security HTTP Response Headers
|
||||
This section discusses Spring Security's support for adding various security headers to the response.
|
||||
|
||||
@ -157,7 +157,7 @@ If necessary, you can disable all of the HTTP Security response headers with the
|
||||
----
|
||||
|
||||
[[headers-cache-control]]
|
||||
==== Cache Control
|
||||
=== Cache Control
|
||||
In the past Spring Security required you to provide your own cache control for your web application.
|
||||
This seemed reasonable at the time, but browser caches have evolved to include caches for secure connections as well.
|
||||
This means that a user may view an authenticated page, log out, and then a malicious user can use the browser history to view the cached page.
|
||||
@ -229,7 +229,7 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
||||
----
|
||||
|
||||
[[headers-content-type-options]]
|
||||
==== Content Type Options
|
||||
=== Content Type Options
|
||||
Historically browsers, including Internet Explorer, would try to guess the content type of a request using https://en.wikipedia.org/wiki/Content_sniffing[content sniffing].
|
||||
This allowed browsers to improve the user experience by guessing the content type on resources that had not specified the content type.
|
||||
For example, if a browser encountered a JavaScript file that did not have the content type specified, it would be able to guess the content type and then execute it.
|
||||
@ -289,7 +289,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-hsts]]
|
||||
==== HTTP Strict Transport Security (HSTS)
|
||||
=== HTTP Strict Transport Security (HSTS)
|
||||
When you type in your bank's website, do you enter mybank.example.com or do you enter https://mybank.example.com[]? If you omit the https protocol, you are potentially vulnerable to https://en.wikipedia.org/wiki/Man-in-the-middle_attack[Man in the Middle attacks].
|
||||
Even if the website performs a redirect to https://mybank.example.com a malicious user could intercept the initial HTTP request and manipulate the response (i.e. redirect to https://mibank.example.com and steal their credentials).
|
||||
|
||||
@ -359,7 +359,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-hpkp]]
|
||||
==== HTTP Public Key Pinning (HPKP)
|
||||
=== HTTP Public Key Pinning (HPKP)
|
||||
HTTP Public Key Pinning (HPKP) is a security feature that tells a web client to associate a specific cryptographic public key with a certain web server to prevent Man in the Middle (MITM) attacks with forged certificates.
|
||||
|
||||
To ensure the authenticity of a server's public key used in TLS sessions, this public key is wrapped into a X.509 certificate which is usually signed by a certificate authority (CA).
|
||||
@ -435,7 +435,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-frame-options]]
|
||||
==== X-Frame-Options
|
||||
=== X-Frame-Options
|
||||
Allowing your website to be added to a frame can be a security issue.
|
||||
For example, using clever CSS styling users could be tricked into clicking on something that they were not intending (https://www.youtube.com/watch?v=3mk0RySeNsU[video demo]).
|
||||
For example, a user that is logged into their bank might click a button that grants access to other users.
|
||||
@ -499,7 +499,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-xss-protection]]
|
||||
==== X-XSS-Protection
|
||||
=== X-XSS-Protection
|
||||
Some browsers have built in support for filtering out https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OWASP-DV-001)[reflected XSS attacks].
|
||||
This is by no means foolproof, but does assist in XSS protection.
|
||||
|
||||
@ -553,7 +553,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-csp]]
|
||||
==== Content Security Policy (CSP)
|
||||
=== Content Security Policy (CSP)
|
||||
|
||||
https://www.w3.org/TR/CSP2/[Content Security Policy (CSP)] is a mechanism that web applications can leverage to mitigate content injection vulnerabilities, such as cross-site scripting (XSS).
|
||||
CSP is a declarative policy that provides a facility for web application authors to declare and ultimately inform the client (user-agent) about the sources from which the web application expects to load resources.
|
||||
@ -606,7 +606,7 @@ Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.ex
|
||||
If the site violates this policy, by attempting to load a script from _evil.com_, the user-agent will send a violation report to the declared URL specified by the _report-uri_ directive, but still allow the violating resource to load nevertheless.
|
||||
|
||||
[[headers-csp-configure]]
|
||||
===== Configuring Content Security Policy
|
||||
==== Configuring Content Security Policy
|
||||
|
||||
It's important to note that Spring Security *_does not add_* Content Security Policy by default.
|
||||
The web application author must declare the security policy(s) to enforce and/or monitor for the protected resources.
|
||||
@ -695,7 +695,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-csp-links]]
|
||||
===== Additional Resources
|
||||
==== Additional Resources
|
||||
|
||||
Applying Content Security Policy to a web application is often a non-trivial undertaking.
|
||||
The following resources may provide further assistance in developing effective security policies for your site.
|
||||
@ -707,7 +707,7 @@ https://developer.mozilla.org/en-US/docs/Web/Security/CSP[CSP Guide - Mozilla De
|
||||
https://www.w3.org/TR/CSP2/[W3C Candidate Recommendation]
|
||||
|
||||
[[headers-referrer]]
|
||||
==== Referrer Policy
|
||||
=== Referrer Policy
|
||||
|
||||
https://www.w3.org/TR/referrer-policy[Referrer Policy] is a mechanism that web applications can leverage to manage the referrer field, which contains the last
|
||||
page the user was on.
|
||||
@ -722,7 +722,7 @@ Referrer-Policy: same-origin
|
||||
The Referrer-Policy response header instructs the browser to let the destination knows the source where the user was previously.
|
||||
|
||||
[[headers-referrer-configure]]
|
||||
===== Configuring Referrer Policy
|
||||
==== Configuring Referrer Policy
|
||||
|
||||
Spring Security *_doesn't add_* Referrer Policy header by default.
|
||||
|
||||
@ -764,7 +764,7 @@ WebSecurityConfigurerAdapter {
|
||||
|
||||
|
||||
[[headers-feature]]
|
||||
==== Feature Policy
|
||||
=== Feature Policy
|
||||
|
||||
https://wicg.github.io/feature-policy/[Feature Policy] is a mechanism that allows web developers to selectively enable, disable, and modify the behavior of certain APIs and web features in the browser.
|
||||
|
||||
@ -777,7 +777,7 @@ With Feature Policy, developers can opt-in to a set of "policies" for the browse
|
||||
These policies restrict what APIs the site can access or modify the browser's default behavior for certain features.
|
||||
|
||||
[[headers-feature-configure]]
|
||||
===== Configuring Feature Policy
|
||||
==== Configuring Feature Policy
|
||||
|
||||
Spring Security *_doesn't add_* Feature Policy header by default.
|
||||
|
||||
@ -815,7 +815,7 @@ WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[headers-clearsitedata]]
|
||||
==== Clear Site Data
|
||||
=== Clear Site Data
|
||||
|
||||
https://www.w3.org/TR/clear-site-data/[Clear Site Data] is a mechanism by which any browser-side data - cookies, local storage, and the like - can be removed when an HTTP response contains this header:
|
||||
|
||||
@ -827,7 +827,7 @@ Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
|
||||
This is a nice clean-up action to perform on logout.
|
||||
|
||||
[[headers-clearsitedata-configure]]
|
||||
===== Configuring Clear Site Data
|
||||
==== Configuring Clear Site Data
|
||||
|
||||
Spring Security *_doesn't add_* the Clear Site Data header by default.
|
||||
|
@ -0,0 +1,7 @@
|
||||
= Protection Against Exploits
|
||||
|
||||
include::csrf.adoc[]
|
||||
|
||||
include::headers.adoc[]
|
||||
|
||||
include::channel.adoc[]
|
@ -1,17 +1,27 @@
|
||||
= Servlet Applications
|
||||
|
||||
include::preface/index.adoc[leveloffset=+1]
|
||||
Spring Security integrates with the Servlet Container by using a standard Servlet `Filter`. This means it works with any application that runs in a Servlet Container. More concretely, you do not need to use Spring in your Servlet-based application to take advantage of Spring Security.
|
||||
|
||||
include::hello/guides.adoc[]
|
||||
|
||||
include::architecture/index.adoc[leveloffset=+1]
|
||||
|
||||
include::test/index.adoc[leveloffset=+1]
|
||||
|
||||
include::web/index.adoc[leveloffset=+1]
|
||||
include::authentication/index.adoc[leveloffset=+1]
|
||||
|
||||
include::authorization/index.adoc[leveloffset=+1]
|
||||
|
||||
include::additional-topics/index.adoc[leveloffset=+1]
|
||||
include::oauth2/index.adoc[leveloffset=+1]
|
||||
|
||||
include::data/index.adoc[leveloffset=+1]
|
||||
include::exploits/index.adoc[leveloffset=+1]
|
||||
|
||||
include::integrations/index.adoc[leveloffset=+1]
|
||||
|
||||
include::java-configuration/index.adoc[leveloffset=+1]
|
||||
|
||||
include::namespace/index.adoc[leveloffset=+1]
|
||||
|
||||
include::test/index.adoc[leveloffset=+1]
|
||||
|
||||
include::crypto/index.adoc[leveloffset=+1]
|
||||
|
||||
include::appendix/index.adoc[leveloffset=+1]
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
[[concurrency]]
|
||||
== Concurrency Support
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[cors]]
|
||||
== CORS
|
||||
|
@ -1,12 +1,11 @@
|
||||
|
||||
[[data]]
|
||||
= Spring Data Integration
|
||||
== Spring Data Integration
|
||||
|
||||
Spring Security provides Spring Data integration that allows referring to the current user within your queries.
|
||||
It is not only useful but necessary to include the user in the queries to support paged results since filtering the results afterwards would not scale.
|
||||
|
||||
[[data-configuration]]
|
||||
== Spring Data & Spring Security Configuration
|
||||
=== Spring Data & Spring Security Configuration
|
||||
|
||||
To use this support, add `org.springframework.security:spring-security-data` dependency and provide a bean of type `SecurityEvaluationContextExtension`.
|
||||
In Java Configuration, this would look like:
|
||||
@ -27,7 +26,7 @@ In XML Configuration, this would look like:
|
||||
----
|
||||
|
||||
[[data-query]]
|
||||
== Security Expressions within @Query
|
||||
=== Security Expressions within @Query
|
||||
|
||||
Now Spring Security can be used within your queries.
|
||||
For example:
|
@ -0,0 +1,19 @@
|
||||
= Integrations
|
||||
|
||||
include::servlet-api.adoc[]
|
||||
|
||||
include::data.adoc[]
|
||||
|
||||
include::concurrency.adoc[]
|
||||
|
||||
include::jackson.adoc[]
|
||||
|
||||
include::localization.adoc[]
|
||||
|
||||
include::mvc.adoc[]
|
||||
|
||||
include::websocket.adoc[]
|
||||
|
||||
include::cors.adoc[]
|
||||
|
||||
include::jsp-taglibs.adoc[]
|
@ -1,5 +1,5 @@
|
||||
[[jackson]]
|
||||
=== Jackson Support
|
||||
== Jackson Support
|
||||
|
||||
Spring Security has added Jackson Support for persisting Spring Security related classes.
|
||||
This can improve the performance of serializing Spring Security related classes when working with distributed sessions (i.e. session replication, Spring Session, etc).
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[taglibs]]
|
||||
== JSP Tag Libraries
|
||||
Spring Security has its own taglib which provides basic support for accessing security information and applying security constraints in JSPs.
|
@ -0,0 +1,36 @@
|
||||
[[localization]]
|
||||
== Localization
|
||||
Spring Security supports localization of exception messages that end users are likely to see.
|
||||
If your application is designed for English-speaking users, you don't need to do anything as by default all Security messages are in English.
|
||||
If you need to support other locales, everything you need to know is contained in this section.
|
||||
|
||||
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:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="messageSource"
|
||||
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
||||
<property name="basename" value="classpath:org/springframework/security/messages"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
The `messages.properties` is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages.
|
||||
This default file is in English.
|
||||
|
||||
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.
|
||||
|
||||
The "contacts" sample application is set up to use localized messages.
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
[[mvc]]
|
||||
== Spring MVC Integration
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
[[servletapi]]
|
||||
== Servlet API integration
|
||||
This section describes how Spring Security is integrated with the Servlet API.
|
@ -0,0 +1,341 @@
|
||||
|
||||
[[jc]]
|
||||
= Java Configuration
|
||||
|
||||
General support for https://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java[Java Configuration] was added to Spring Framework in Spring 3.1.
|
||||
Since Spring Security 3.2 there has been Spring Security Java Configuration support which enables users to easily configure Spring Security without the use of any XML.
|
||||
|
||||
If you are familiar with the <<ns-config>> then you should find quite a few similarities between it and the Security Java Configuration support.
|
||||
|
||||
NOTE: Spring Security provides https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig[lots of sample applications] which demonstrate the use of Spring Security Java Configuration.
|
||||
|
||||
== Hello Web Security Java Configuration
|
||||
|
||||
The first step is to create our Spring Security Java Configuration.
|
||||
The configuration creates a Servlet Filter known as the `springSecurityFilterChain` which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, etc) within your application.
|
||||
You can find the most basic example of a Spring Security Java Configuration below:
|
||||
|
||||
[[jc-hello-wsca]]
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.security.config.annotation.authentication.builders.*;
|
||||
import org.springframework.security.config.annotation.web.configuration.*;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
There really isn't much to this configuration, but it does a lot.
|
||||
You can find a summary of the features below:
|
||||
|
||||
* Require authentication to every URL in your application
|
||||
* Generate a login form for you
|
||||
* Allow the user with the *Username* _user_ and the *Password* _password_ to authenticate with form based authentication
|
||||
* Allow the user to logout
|
||||
* https://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attack] prevention
|
||||
* https://en.wikipedia.org/wiki/Session_fixation[Session Fixation] protection
|
||||
* Security Header integration
|
||||
** https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HTTP Strict Transport Security] for secure requests
|
||||
** https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx[X-Content-Type-Options] integration
|
||||
** Cache Control (can be overridden later by your application to allow caching of your static resources)
|
||||
** https://msdn.microsoft.com/en-us/library/dd565647(v=vs.85).aspx[X-XSS-Protection] integration
|
||||
** X-Frame-Options integration to help prevent https://en.wikipedia.org/wiki/Clickjacking[Clickjacking]
|
||||
* Integrate with the following Servlet API methods
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()[HttpServletRequest#getRemoteUser()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal()[HttpServletRequest#getUserPrincipal()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)[HttpServletRequest#isUserInRole(java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String,%20java.lang.String)[HttpServletRequest#login(java.lang.String, java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#logout()[HttpServletRequest#logout()]
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer
|
||||
|
||||
The next step is to register the `springSecurityFilterChain` with the war.
|
||||
This can be done in Java Configuration with https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-container-config[Spring's WebApplicationInitializer support] in a Servlet 3.0+ environment.
|
||||
Not suprisingly, Spring Security provides a base class `AbstractSecurityWebApplicationInitializer` that will ensure the `springSecurityFilterChain` gets registered for you.
|
||||
The way in which we use `AbstractSecurityWebApplicationInitializer` differs depending on if we are already using Spring or if Spring Security is the only Spring component in our application.
|
||||
|
||||
* <<abstractsecuritywebapplicationinitializer-without-existing-spring>> - Use these instructions if you are not using Spring already
|
||||
* <<abstractsecuritywebapplicationinitializer-with-spring-mvc>> - Use these instructions if you are already using Spring
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer without Existing Spring
|
||||
|
||||
If you are not using Spring or Spring MVC, you will need to pass in the `WebSecurityConfig` into the superclass to ensure the configuration is picked up.
|
||||
You can find an example below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
public SecurityWebApplicationInitializer() {
|
||||
super(WebSecurityConfig.class);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The `SecurityWebApplicationInitializer` will do the following things:
|
||||
|
||||
* Automatically register the springSecurityFilterChain Filter for every URL in your application
|
||||
* Add a ContextLoaderListener that loads the <<jc-hello-wsca,WebSecurityConfig>>.
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer with Spring MVC
|
||||
|
||||
If we were using Spring elsewhere in our application we probably already had a `WebApplicationInitializer` that is loading our Spring Configuration.
|
||||
If we use the previous configuration we would get an error.
|
||||
Instead, we should register Spring Security with the existing `ApplicationContext`.
|
||||
For example, if we were using Spring MVC our `SecurityWebApplicationInitializer` would look something like the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
This would simply only register the springSecurityFilterChain Filter for every URL in your application.
|
||||
After that we would ensure that `WebSecurityConfig` was loaded in our existing ApplicationInitializer.
|
||||
For example, if we were using Spring MVC it would be added in the `getRootConfigClasses()`
|
||||
|
||||
[[message-web-application-inititializer-java]]
|
||||
[source,java]
|
||||
----
|
||||
public class MvcWebApplicationInitializer extends
|
||||
AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getRootConfigClasses() {
|
||||
return new Class[] { WebSecurityConfig.class };
|
||||
}
|
||||
|
||||
// ... other overrides ...
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-httpsecurity]]
|
||||
== HttpSecurity
|
||||
|
||||
Thus far our <<jc-hello-wsca,WebSecurityConfig>> only contains information about how to authenticate our users.
|
||||
How does Spring Security know that we want to require all users to be authenticated?
|
||||
How does Spring Security know we want to support form based authentication?
|
||||
Actually, there is an configuration class that is being invoked behind the scenes called `WebSecurityConfigurerAdapter`.
|
||||
It has a method called `configure` with the following default implementation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults())
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
----
|
||||
|
||||
The default configuration above:
|
||||
|
||||
* Ensures that any request to our application requires the user to be authenticated
|
||||
* Allows users to authenticate with form based login
|
||||
* Allows users to authenticate with HTTP Basic authentication
|
||||
|
||||
You will notice that this configuration is quite similar the XML Namespace configuration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<form-login />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
== Multiple HttpSecurity
|
||||
|
||||
We can configure multiple HttpSecurity instances just as we can have multiple `<http>` blocks.
|
||||
The key is to extend the `WebSecurityConfigurerAdapter` multiple times.
|
||||
For example, the following is an example of having a different configuration for URL's that start with `/api/`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class MultiHttpSecurityConfig {
|
||||
@Bean <1>
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build());
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(1) <2>
|
||||
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.antMatcher("/api/**") <3>
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().hasRole("ADMIN")
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration <4>
|
||||
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<1> Configure Authentication as normal
|
||||
<2> Create an instance of `WebSecurityConfigurerAdapter` that contains `@Order` to specify which `WebSecurityConfigurerAdapter` should be considered first.
|
||||
<3> The `http.antMatcher` states that this `HttpSecurity` will only be applicable to URLs that start with `/api/`
|
||||
<4> Create another instance of `WebSecurityConfigurerAdapter`.
|
||||
If the URL does not start with `/api/` this configuration will be used.
|
||||
This configuration is considered after `ApiWebSecurityConfigurationAdapter` since it has an `@Order` value after `1` (no `@Order` defaults to last).
|
||||
|
||||
[[jc-custom-dsls]]
|
||||
== Custom DSLs
|
||||
|
||||
You can provide your own custom DSLs in Spring Security.
|
||||
For example, you might have something that looks like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
|
||||
private boolean flag;
|
||||
|
||||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
// any method that adds another configurer
|
||||
// must be done in the init method
|
||||
http.csrf().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
|
||||
// here we lookup from the ApplicationContext. You can also just create a new instance.
|
||||
MyFilter myFilter = context.getBean(MyFilter.class);
|
||||
myFilter.setFlag(flag);
|
||||
http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
public MyCustomDsl flag(boolean value) {
|
||||
this.flag = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static MyCustomDsl customDsl() {
|
||||
return new MyCustomDsl();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: This is actually how methods like `HttpSecurity.authorizeRequests()` are implemented.
|
||||
|
||||
The custom DSL can then be used like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl())
|
||||
.flag(true)
|
||||
.and()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The code is invoked in the following order:
|
||||
|
||||
* Code in `Config`s configure method is invoked
|
||||
* Code in `MyCustomDsl`s init method is invoked
|
||||
* Code in `MyCustomDsl`s configure method is invoked
|
||||
|
||||
If you want, you can have `WebSecurityConfiguerAdapter` add `MyCustomDsl` by default by using `SpringFactories`.
|
||||
For example, you would create a resource on the classpath named `META-INF/spring.factories` with the following contents:
|
||||
|
||||
.META-INF/spring.factories
|
||||
----
|
||||
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl
|
||||
----
|
||||
|
||||
Users wishing to disable the default can do so explicitly.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl()).disable()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[post-processing-configured-objects]]
|
||||
== Post Processing Configured Objects
|
||||
|
||||
Spring Security's Java Configuration does not expose every property of every object that it configures.
|
||||
This simplifies the configuration for a majority of users.
|
||||
Afterall, if every property was exposed, users could use standard bean configuration.
|
||||
|
||||
While there are good reasons to not directly expose every property, users may still need more advanced configuration options.
|
||||
To address this Spring Security introduces the concept of an `ObjectPostProcessor` which can be used to modify or replace many of the Object instances created by the Java Configuration.
|
||||
For example, if you wanted to configure the `filterSecurityPublishAuthorizationSuccess` property on `FilterSecurityInterceptor` you could use the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
|
||||
public <O extends FilterSecurityInterceptor> O postProcess(
|
||||
O fsi) {
|
||||
fsi.setPublishAuthorizationSuccess(true);
|
||||
return fsi;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
----
|
@ -0,0 +1,403 @@
|
||||
|
||||
[[ns-config]]
|
||||
= Security Namespace Configuration
|
||||
|
||||
|
||||
== Introduction
|
||||
Namespace configuration has been available since version 2.0 of the Spring Framework.
|
||||
It allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema.
|
||||
You can find more information in the Spring https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/[Reference Documentation].
|
||||
A namespace element can be used simply to allow a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax which more closely matches the problem domain and hides the underlying complexity from the user.
|
||||
A simple element may conceal the fact that multiple beans and processing steps are being added to the application context.
|
||||
For example, adding the following element from the security namespace to an application context will start up an embedded LDAP server for testing use within the application:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<security:ldap-server />
|
||||
----
|
||||
|
||||
This is much simpler than wiring up the equivalent Apache Directory Server beans.
|
||||
The most common alternative configuration requirements are supported by attributes on the `ldap-server` element and the user is isolated from worrying about which beans they need to create and what the bean property names are.
|
||||
footnote:[You can find out more about the use of the `ldap-server` element in the chapter on pass:specialcharacters,macros[<<ldap>>].].
|
||||
Use of a good XML editor while editing the application context file should provide information on the attributes and elements that are available.
|
||||
We would recommend that you try out the https://spring.io/tools/sts[Spring Tool Suite] as it has special features for working with standard Spring namespaces.
|
||||
|
||||
|
||||
To start using the security namespace in your application context, you need to have the `spring-security-config` jar on your classpath.
|
||||
Then all you need to do is add the schema declaration to your application context file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans>
|
||||
----
|
||||
|
||||
In many of the examples you will see (and in the sample applications), we will often use "security" as the default namespace rather than "beans", which means we can omit the prefix on all the security namespace elements, making the content easier to read.
|
||||
You may also want to do this if you have your application context divided up into separate files and have most of your security configuration in one of them.
|
||||
Your security application context file would then start like this
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans:beans>
|
||||
----
|
||||
|
||||
We'll assume this syntax is being used from now on in this chapter.
|
||||
|
||||
|
||||
=== Design of the Namespace
|
||||
The namespace is designed to capture the most common uses of the framework and provide a simplified and concise syntax for enabling them within an application.
|
||||
The design is based around the large-scale dependencies within the framework, and can be divided up into the following areas:
|
||||
|
||||
* __Web/HTTP Security__ - the most complex part.
|
||||
Sets up the filters and related service beans used to apply the framework authentication mechanisms, to secure URLs, render login and error pages and much more.
|
||||
|
||||
* __Business Object (Method) Security__ - options for securing the service layer.
|
||||
|
||||
* __AuthenticationManager__ - handles authentication requests from other parts of the framework.
|
||||
|
||||
* __AccessDecisionManager__ - provides access decisions for web and method security.
|
||||
A default one will be registered, but you can also choose to use a custom one, declared using normal Spring bean syntax.
|
||||
|
||||
* __AuthenticationProvider__s - mechanisms against which the authentication manager authenticates users.
|
||||
The namespace provides supports for several standard options and also a means of adding custom beans declared using a traditional syntax.
|
||||
|
||||
* __UserDetailsService__ - closely related to authentication providers, but often also required by other beans.
|
||||
|
||||
We'll see how to configure these in the following sections.
|
||||
|
||||
[[ns-getting-started]]
|
||||
== Getting Started with Security Namespace Configuration
|
||||
In this section, we'll look at how you can build up a namespace configuration to use some of the main features of the framework.
|
||||
Let's assume you initially want to get up and running as quickly as possible and add authentication support and access control to an existing web application, with a few test logins.
|
||||
Then we'll look at how to change over to authenticating against a database or other security repository.
|
||||
In later sections we'll introduce more advanced namespace configuration options.
|
||||
|
||||
[[ns-web-xml]]
|
||||
=== web.xml Configuration
|
||||
The first thing you need to do is add the following filter declaration to your `web.xml` file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
----
|
||||
|
||||
This provides a hook into the Spring Security web infrastructure.
|
||||
`DelegatingFilterProxy` is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in your application context.
|
||||
In this case, the bean is named "springSecurityFilterChain", which is an internal infrastructure bean created by the namespace to handle web security.
|
||||
Note that you should not use this bean name yourself.
|
||||
Once you've added this to your `web.xml`, you're ready to start editing your application context file.
|
||||
Web security services are configured using the `<http>` element.
|
||||
|
||||
[[ns-minimal]]
|
||||
=== A Minimal <http> Configuration
|
||||
All you need to enable web security to begin with is
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="hasRole('USER')" />
|
||||
<form-login />
|
||||
<logout />
|
||||
</http>
|
||||
----
|
||||
|
||||
Which says that we want all URLs within our application to be secured, requiring the role `ROLE_USER` to access them, we want to log in to the application using a form with username and password, and that we want a logout URL registered which will allow us to log out of the application.
|
||||
`<http>` element is the parent for all web-related namespace functionality.
|
||||
The `<intercept-url>` element defines a `pattern` which is matched against the URLs of incoming requests using an ant path style syntax footnote:[See the section on pass:specialcharacters,macros[<<request-matching>>] in the Web Application Infrastructure chapter for more details on how matches are actually performed.].
|
||||
You can also use regular-expression matching as an alternative (see the namespace appendix for more details).
|
||||
The `access` attribute defines the access requirements for requests matching the given pattern.
|
||||
With the default configuration, this is typically a comma-separated list of roles, one of which a user must have to be allowed to make the request.
|
||||
The prefix "ROLE_" is a marker which indicates that a simple comparison with the user's authorities should be made.
|
||||
In other words, a normal role-based check should be used.
|
||||
Access-control in Spring Security is not limited to the use of simple roles (hence the use of the prefix to differentiate between different types of security attributes).
|
||||
We'll see later how the interpretation can vary footnote:[The interpretation of the comma-separated values in the `access` attribute depends on the implementation of the <<ns-access-manager,AccessDecisionManager>> which is used.].
|
||||
In Spring Security 3.0, the attribute can also be populated with an pass:specialcharacters,macros[<<el-access,EL expression>>].
|
||||
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
|
||||
You can use multiple `<intercept-url>` elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used.
|
||||
So you must put the most specific matches at the top.
|
||||
You can also add a `method` attribute to limit the match to a particular HTTP method (`GET`, `POST`, `PUT` etc.).
|
||||
|
||||
===
|
||||
|
||||
To add some users, you can define a set of test data directly in the namespace:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
|
||||
NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
|
||||
in samples easier. Normally passwords should be hashed using BCrypt -->
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
This is an example of a secure way of storing the same passwords.
|
||||
The password is prefixed with `{bcrypt}` to instruct `DelegatingPasswordEncoder`, which supports any configured `PasswordEncoder` for matching, that the passwords are hashed using BCrypt:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
|
||||
authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
|
||||
authorities="ROLE_USER" />
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[subs="quotes"]
|
||||
****
|
||||
If you are familiar with pre-namespace versions of the framework, you can probably already guess roughly what's going on here.
|
||||
The `<http>` element is responsible for creating a `FilterChainProxy` and the filter beans which it uses.
|
||||
Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined.
|
||||
|
||||
The `<authentication-provider>` element creates a `DaoAuthenticationProvider` bean and the `<user-service>` element creates an `InMemoryDaoImpl`.
|
||||
All `authentication-provider` elements must be children of the `<authentication-manager>` element, which creates a `ProviderManager` and registers the authentication providers with it.
|
||||
You can find more detailed information on the beans that are created in the <<appendix-namespace,namespace appendix>>.
|
||||
It's worth cross-checking this if you want to start understanding what the important classes in the framework are and how they are used, particularly if you want to customise things later.
|
||||
****
|
||||
|
||||
The configuration above defines two users, their passwords and their roles within the application (which will be used for access control).
|
||||
It is also possible to load user information from a standard properties file using the `properties` attribute on `user-service`.
|
||||
See the section on <<core-services-in-memory-service,in-memory authentication>> for more details on the file format.
|
||||
Using the `<authentication-provider>` element means that the user information will be used by the authentication manager to process authentication requests.
|
||||
You can have multiple `<authentication-provider>` elements to define different authentication sources and each will be consulted in turn.
|
||||
|
||||
At this point you should be able to start up your application and you will be required to log in to proceed.
|
||||
Try it out, or try experimenting with the "tutorial" sample application that comes with the project.
|
||||
|
||||
[[ns-form-target]]
|
||||
==== Setting a Default Post-Login Destination
|
||||
If a form login isn't prompted by an attempt to access a protected resource, the `default-target-url` option comes into play.
|
||||
This is the URL the user will be taken to after successfully logging in, and defaults to "/".
|
||||
You can also configure things so that the user __always__ ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the `always-use-default-target` attribute to "true".
|
||||
This is useful if your application always requires that the user starts at a "home" page, for example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http pattern="/login.htm*" security="none"/>
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern='/**' access='ROLE_USER' />
|
||||
<form-login login-page='/login.htm' default-target-url='/home.htm'
|
||||
always-use-default-target='true' />
|
||||
</http>
|
||||
----
|
||||
|
||||
For even more control over the destination, you can use the `authentication-success-handler-ref` attribute as an alternative to `default-target-url`.
|
||||
The referenced bean should be an instance of `AuthenticationSuccessHandler`.
|
||||
You'll find more on this in the <<form-login-flow-handling,Core Filters>> chapter and also in the namespace appendix, as well as information on how to customize the flow when authentication fails.
|
||||
|
||||
[[ns-web-advanced]]
|
||||
== Advanced Web Features
|
||||
|
||||
[[ns-custom-filters]]
|
||||
=== Adding in Your Own Filters
|
||||
If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services.
|
||||
You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example).
|
||||
Or you might want to use a customized version of a standard namespace filter, such as the `UsernamePasswordAuthenticationFilter` which is created by the `<form-login>` element, taking advantage of some of the extra configuration options which are available by using the bean explicitly.
|
||||
How can you do this with namespace configuration, since the filter chain is not directly exposed?
|
||||
|
||||
The order of the filters is always strictly enforced when using the namespace.
|
||||
When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context.
|
||||
In version 3.0+ the sorting is now done at the bean metadata level, before the classes have been instantiated.
|
||||
This has implications for how you add your own filters to the stack as the entire filter list must be known during the parsing of the `<http>` element, so the syntax has changed slightly in 3.0.
|
||||
===
|
||||
|
||||
The filters, aliases and namespace elements/attributes which create the filters are shown in <<filter-stack>>.
|
||||
The filters are listed in the order in which they occur in the filter chain.
|
||||
|
||||
[[filter-stack]]
|
||||
.Standard Filter Aliases and Ordering
|
||||
|===
|
||||
| Alias | Filter Class | Namespace Element or Attribute
|
||||
|
||||
| CHANNEL_FILTER
|
||||
| `ChannelProcessingFilter`
|
||||
| `http/intercept-url@requires-channel`
|
||||
|
||||
| SECURITY_CONTEXT_FILTER
|
||||
| `SecurityContextPersistenceFilter`
|
||||
| `http`
|
||||
|
||||
| CONCURRENT_SESSION_FILTER
|
||||
| `ConcurrentSessionFilter`
|
||||
| `session-management/concurrency-control`
|
||||
|
||||
| HEADERS_FILTER
|
||||
| `HeaderWriterFilter`
|
||||
| `http/headers`
|
||||
|
||||
| CSRF_FILTER
|
||||
| `CsrfFilter`
|
||||
| `http/csrf`
|
||||
|
||||
| LOGOUT_FILTER
|
||||
| `LogoutFilter`
|
||||
| `http/logout`
|
||||
|
||||
| X509_FILTER
|
||||
| `X509AuthenticationFilter`
|
||||
| `http/x509`
|
||||
|
||||
| PRE_AUTH_FILTER
|
||||
| `AbstractPreAuthenticatedProcessingFilter` Subclasses
|
||||
| N/A
|
||||
|
||||
| CAS_FILTER
|
||||
| `CasAuthenticationFilter`
|
||||
| N/A
|
||||
|
||||
| FORM_LOGIN_FILTER
|
||||
| `UsernamePasswordAuthenticationFilter`
|
||||
| `http/form-login`
|
||||
|
||||
| BASIC_AUTH_FILTER
|
||||
| `BasicAuthenticationFilter`
|
||||
| `http/http-basic`
|
||||
|
||||
| SERVLET_API_SUPPORT_FILTER
|
||||
| `SecurityContextHolderAwareRequestFilter`
|
||||
| `http/@servlet-api-provision`
|
||||
|
||||
| JAAS_API_SUPPORT_FILTER
|
||||
| `JaasApiIntegrationFilter`
|
||||
| `http/@jaas-api-provision`
|
||||
|
||||
| REMEMBER_ME_FILTER
|
||||
| `RememberMeAuthenticationFilter`
|
||||
| `http/remember-me`
|
||||
|
||||
| ANONYMOUS_FILTER
|
||||
| `AnonymousAuthenticationFilter`
|
||||
| `http/anonymous`
|
||||
|
||||
| SESSION_MANAGEMENT_FILTER
|
||||
| `SessionManagementFilter`
|
||||
| `session-management`
|
||||
|
||||
| EXCEPTION_TRANSLATION_FILTER
|
||||
| `ExceptionTranslationFilter`
|
||||
| `http`
|
||||
|
||||
| FILTER_SECURITY_INTERCEPTOR
|
||||
| `FilterSecurityInterceptor`
|
||||
| `http`
|
||||
|
||||
| SWITCH_USER_FILTER
|
||||
| `SwitchUserFilter`
|
||||
| N/A
|
||||
|===
|
||||
|
||||
You can add your own filter to the stack, using the `custom-filter` element and one of these names to specify the position your filter should appear at:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
|
||||
</http>
|
||||
|
||||
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
|
||||
----
|
||||
|
||||
You can also use the `after` or `before` attributes if you want your filter to be inserted before or after another filter in the stack.
|
||||
The names "FIRST" and "LAST" can be used with the `position` attribute to indicate that you want your filter to appear before or after the entire stack, respectively.
|
||||
|
||||
.Avoiding filter position conflicts
|
||||
[TIP]
|
||||
===
|
||||
|
||||
If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake.
|
||||
Remove any elements which create filters whose functionality you want to replace.
|
||||
|
||||
Note that you can't replace filters which are created by the use of the `<http>` element itself - `SecurityContextPersistenceFilter`, `ExceptionTranslationFilter` or `FilterSecurityInterceptor`.
|
||||
Some other filters are added by default, but you can disable them.
|
||||
An `AnonymousAuthenticationFilter` is added by default and unless you have <<ns-session-fixation,session-fixation protection>> disabled, a `SessionManagementFilter` will also be added to the filter chain.
|
||||
|
||||
===
|
||||
|
||||
If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too.
|
||||
|
||||
|
||||
|
||||
[[ns-method-security]]
|
||||
== Method Security
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods.
|
||||
It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation.
|
||||
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
|
||||
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
[[ns-access-manager]]
|
||||
== The Default AccessDecisionManager
|
||||
This section assumes you have some knowledge of the underlying architecture for access-control within Spring Security.
|
||||
If you don't you can skip it and come back to it later, as this section is only really relevant for people who need to do some customization in order to use more than simple role-based security.
|
||||
|
||||
When you use a namespace configuration, a default instance of `AccessDecisionManager` is automatically registered for you and will be used for making access decisions for method invocations and web URL access, based on the access attributes you specify in your `intercept-url` and `protect-pointcut` declarations (and in annotations if you are using annotation secured methods).
|
||||
|
||||
The default strategy is to use an `AffirmativeBased` `AccessDecisionManager` with a `RoleVoter` and an `AuthenticatedVoter`.
|
||||
You can find out more about these in the chapter on <<authz-arch,authorization>>.
|
||||
|
||||
|
||||
[[ns-custom-access-mgr]]
|
||||
=== Customizing the AccessDecisionManager
|
||||
If you need to use a more complicated access control strategy then it is easy to set an alternative for both method and web security.
|
||||
|
||||
For method security, you do this by setting the `access-decision-manager-ref` attribute on `global-method-security` to the `id` of the appropriate `AccessDecisionManager` bean in the application context:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</global-method-security>
|
||||
----
|
||||
|
||||
The syntax for web security is the same, but on the `http` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</http>
|
||||
----
|
@ -0,0 +1,7 @@
|
||||
= OAuth2
|
||||
|
||||
include::oauth2-login.adoc[]
|
||||
|
||||
include::oauth2-client.adoc[]
|
||||
|
||||
include::oauth2-resourceserver.adoc[]
|
@ -1,5 +1,401 @@
|
||||
[[oauth2login]]
|
||||
== OAuth 2.0 Login
|
||||
|
||||
The OAuth 2.0 Login feature provides an application with the capability to have users log in to the application by using their existing account at an OAuth 2.0 Provider (e.g. GitHub) or OpenID Connect 1.0 Provider (such as Google).
|
||||
OAuth 2.0 Login implements the use cases: "Login with Google" or "Login with GitHub".
|
||||
|
||||
NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0].
|
||||
|
||||
|
||||
[[oauth2login-sample-boot]]
|
||||
=== Spring Boot 2.x Sample
|
||||
|
||||
Spring Boot 2.x brings full auto-configuration capabilities for OAuth 2.0 Login.
|
||||
|
||||
This section shows how to configure the {gh-samples-url}/boot/oauth2login[*OAuth 2.0 Login sample*] using _Google_ as the _Authentication Provider_ and covers the following topics:
|
||||
|
||||
* <<oauth2login-sample-initial-setup,Initial setup>>
|
||||
* <<oauth2login-sample-redirect-uri,Setting the redirect URI>>
|
||||
* <<oauth2login-sample-application-config,Configure application.yml>>
|
||||
* <<oauth2login-sample-boot-application,Boot up the application>>
|
||||
|
||||
|
||||
[[oauth2login-sample-initial-setup]]
|
||||
==== Initial setup
|
||||
|
||||
To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials.
|
||||
|
||||
NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified].
|
||||
|
||||
Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the section, "Setting up OAuth 2.0".
|
||||
|
||||
After completing the "Obtain OAuth 2.0 credentials" instructions, you should have a new OAuth Client with credentials consisting of a Client ID and a Client Secret.
|
||||
|
||||
|
||||
[[oauth2login-sample-redirect-uri]]
|
||||
==== Setting the redirect URI
|
||||
|
||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google and have granted access to the OAuth Client _(<<oauth2login-sample-initial-setup,created in the previous step>>)_ on the Consent page.
|
||||
|
||||
In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`.
|
||||
|
||||
TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`.
|
||||
The *_registrationId_* is a unique identifier for the <<oauth2Client-client-registration,ClientRegistration>>.
|
||||
|
||||
|
||||
[[oauth2login-sample-application-config]]
|
||||
==== Configure application.yml
|
||||
|
||||
Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_.
|
||||
To do so:
|
||||
|
||||
. Go to `application.yml` and set the following configuration:
|
||||
+
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration: <1>
|
||||
google: <2>
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
+
|
||||
.OAuth Client properties
|
||||
====
|
||||
<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties.
|
||||
<2> Following the base property prefix is the ID for the <<oauth2Client-client-registration,ClientRegistration>>, such as google.
|
||||
====
|
||||
|
||||
. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier.
|
||||
|
||||
|
||||
[[oauth2login-sample-boot-application]]
|
||||
==== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.x sample and go to `http://localhost:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
||||
|
||||
Click on the Google link, and you are then redirected to Google for authentication.
|
||||
|
||||
After authenticating with your Google account credentials, the next page presented to you is the Consent screen.
|
||||
The Consent screen asks you to either allow or deny access to the OAuth Client you created earlier.
|
||||
Click *Allow* to authorize the OAuth Client to access your email address and basic profile information.
|
||||
|
||||
At this point, the OAuth Client retrieves your email address and basic profile information from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session.
|
||||
|
||||
|
||||
[[oauth2login-boot-property-mappings]]
|
||||
=== Spring Boot 2.x Property Mappings
|
||||
|
||||
The following table outlines the mapping of the Spring Boot 2.x OAuth Client properties to the <<oauth2Client-client-registration,ClientRegistration>> properties.
|
||||
|
||||
|===
|
||||
|Spring Boot 2.x |ClientRegistration
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_`
|
||||
|`registrationId`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-id`
|
||||
|`clientId`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-secret`
|
||||
|`clientSecret`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-authentication-method`
|
||||
|`clientAuthenticationMethod`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.authorization-grant-type`
|
||||
|`authorizationGrantType`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.redirect-uri`
|
||||
|`redirectUriTemplate`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.scope`
|
||||
|`scopes`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-name`
|
||||
|`clientName`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.authorization-uri`
|
||||
|`providerDetails.authorizationUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.token-uri`
|
||||
|`providerDetails.tokenUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.jwk-set-uri`
|
||||
|`providerDetails.jwkSetUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.user-info-uri`
|
||||
|`providerDetails.userInfoEndpoint.uri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.user-info-authentication-method`
|
||||
|`providerDetails.userInfoEndpoint.authenticationMethod`
|
||||
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.userNameAttribute`
|
||||
|`providerDetails.userInfoEndpoint.userNameAttributeName`
|
||||
|===
|
||||
|
||||
|
||||
[[oauth2login-common-oauth2-provider]]
|
||||
=== CommonOAuth2Provider
|
||||
|
||||
`CommonOAuth2Provider` pre-defines a set of default client properties for a number of well known providers: Google, GitHub, Facebook, and Okta.
|
||||
|
||||
For example, the `authorization-uri`, `token-uri`, and `user-info-uri` do not change often for a Provider.
|
||||
Therefore, it makes sense to provide default values in order to reduce the required configuration.
|
||||
|
||||
As demonstrated previously, when we <<oauth2login-sample-application-config,configured a Google client>>, only the `client-id` and `client-secret` properties are required.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
google:
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
|
||||
[TIP]
|
||||
The auto-defaulting of client properties works seamlessly here because the `registrationId` (`google`) matches the `GOOGLE` `enum` (case-insensitive) in `CommonOAuth2Provider`.
|
||||
|
||||
For cases where you may want to specify a different `registrationId`, such as `google-login`, you can still leverage auto-defaulting of client properties by configuring the `provider` property.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
google-login: <1>
|
||||
provider: google <2>
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
<1> The `registrationId` is set to `google-login`.
|
||||
<2> The `provider` property is set to `google`, which will leverage the auto-defaulting of client properties set in `CommonOAuth2Provider.GOOGLE.getBuilder()`.
|
||||
|
||||
|
||||
[[oauth2login-custom-provider-properties]]
|
||||
=== Configuring Custom Provider Properties
|
||||
|
||||
There are some OAuth 2.0 Providers that support multi-tenancy, which results in different protocol endpoints for each tenant (or sub-domain).
|
||||
|
||||
For example, an OAuth Client registered with Okta is assigned to a specific sub-domain and have their own protocol endpoints.
|
||||
|
||||
For these cases, Spring Boot 2.x provides the following base property for configuring custom provider properties: `spring.security.oauth2.client.provider._[providerId]_`.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
okta:
|
||||
client-id: okta-client-id
|
||||
client-secret: okta-client-secret
|
||||
provider:
|
||||
okta: <1>
|
||||
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
|
||||
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
|
||||
user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
|
||||
user-name-attribute: sub
|
||||
jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
|
||||
----
|
||||
|
||||
<1> The base property (`spring.security.oauth2.client.provider.okta`) allows for custom configuration of protocol endpoint locations.
|
||||
|
||||
|
||||
[[oauth2login-override-boot-autoconfig]]
|
||||
=== Overriding Spring Boot 2.x Auto-configuration
|
||||
|
||||
The Spring Boot 2.x auto-configuration class for OAuth Client support is `OAuth2ClientAutoConfiguration`.
|
||||
|
||||
It performs the following tasks:
|
||||
|
||||
* Registers a `ClientRegistrationRepository` `@Bean` composed of `ClientRegistration`(s) from the configured OAuth Client properties.
|
||||
* Provides a `WebSecurityConfigurerAdapter` `@Configuration` and enables OAuth 2.0 Login through `httpSecurity.oauth2Login()`.
|
||||
|
||||
If you need to override the auto-configuration based on your specific requirements, you may do so in the following ways:
|
||||
|
||||
* <<oauth2login-register-clientregistrationrepository-bean,Register a ClientRegistrationRepository @Bean>>
|
||||
* <<oauth2login-provide-websecurityconfigureradapter,Provide a WebSecurityConfigurerAdapter>>
|
||||
* <<oauth2login-completely-override-autoconfiguration,Completely Override the Auto-configuration>>
|
||||
|
||||
|
||||
[[oauth2login-register-clientregistrationrepository-bean]]
|
||||
==== Register a ClientRegistrationRepository @Bean
|
||||
|
||||
The following example shows how to register a `ClientRegistrationRepository` `@Bean`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return ClientRegistration.withRegistrationId("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
|
||||
.scope("openid", "profile", "email", "address", "phone")
|
||||
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
|
||||
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
|
||||
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
.userNameAttributeName(IdTokenClaimNames.SUB)
|
||||
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
|
||||
.clientName("Google")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-provide-websecurityconfigureradapter]]
|
||||
==== Provide a WebSecurityConfigurerAdapter
|
||||
|
||||
The following example shows how to provide a `WebSecurityConfigurerAdapter` with `@EnableWebSecurity` and enable OAuth 2.0 login through `httpSecurity.oauth2Login()`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-completely-override-autoconfiguration]]
|
||||
==== Completely Override the Auto-configuration
|
||||
|
||||
The following example shows how to completely override the auto-configuration by registering a `ClientRegistrationRepository` `@Bean` and providing a `WebSecurityConfigurerAdapter`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@EnableWebSecurity
|
||||
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return ClientRegistration.withRegistrationId("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
|
||||
.scope("openid", "profile", "email", "address", "phone")
|
||||
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
|
||||
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
|
||||
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
.userNameAttributeName(IdTokenClaimNames.SUB)
|
||||
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
|
||||
.clientName("Google")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-javaconfig-wo-boot]]
|
||||
=== Java Configuration without Spring Boot 2.x
|
||||
|
||||
If you are not able to use Spring Boot 2.x and would like to configure one of the pre-defined providers in `CommonOAuth2Provider` (for example, Google), apply the following configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@EnableWebSecurity
|
||||
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientService authorizedClientService(
|
||||
ClientRegistrationRepository clientRegistrationRepository) {
|
||||
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientRepository authorizedClientRepository(
|
||||
OAuth2AuthorizedClientService authorizedClientService) {
|
||||
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[oauth2login-advanced]]
|
||||
== OAuth 2.0 Login -- Advanced Configuration
|
||||
=== OAuth 2.0 Login -- Advanced Configuration
|
||||
|
||||
`HttpSecurity.oauth2Login()` provides a number of configuration options for customizing OAuth 2.0 Login.
|
||||
The main configuration options are grouped into their protocol endpoint counterparts.
|
||||
@ -108,7 +504,7 @@ The following sections go into more detail on each of the configuration options
|
||||
|
||||
|
||||
[[oauth2login-advanced-login-page]]
|
||||
=== OAuth 2.0 Login Page
|
||||
==== OAuth 2.0 Login Page
|
||||
|
||||
By default, the OAuth 2.0 Login Page is auto-generated by the `DefaultLoginPageGeneratingFilter`.
|
||||
The default login page shows each configured OAuth Client with its `ClientRegistration.clientName` as a link, which is capable of initiating the Authorization Request (or OAuth 2.0 Login).
|
||||
@ -172,7 +568,7 @@ The following line shows an example:
|
||||
|
||||
|
||||
[[oauth2login-advanced-redirection-endpoint]]
|
||||
=== Redirection Endpoint
|
||||
==== Redirection Endpoint
|
||||
|
||||
The Redirection Endpoint is used by the Authorization Server for returning the Authorization Response (which contains the authorization credentials) to the client via the Resource Owner user-agent.
|
||||
|
||||
@ -222,7 +618,7 @@ return CommonOAuth2Provider.GOOGLE.getBuilder("google")
|
||||
|
||||
|
||||
[[oauth2login-advanced-userinfo-endpoint]]
|
||||
=== UserInfo Endpoint
|
||||
==== UserInfo Endpoint
|
||||
|
||||
The UserInfo Endpoint includes a number of configuration options, as described in the following sub-sections:
|
||||
|
||||
@ -233,7 +629,7 @@ The UserInfo Endpoint includes a number of configuration options, as described i
|
||||
|
||||
|
||||
[[oauth2login-advanced-map-authorities]]
|
||||
==== Mapping User Authorities
|
||||
===== Mapping User Authorities
|
||||
|
||||
After the user successfully authenticates with the OAuth 2.0 Provider, the `OAuth2User.getAuthorities()` (or `OidcUser.getAuthorities()`) may be mapped to a new set of `GrantedAuthority` instances, which will be supplied to `OAuth2AuthenticationToken` when completing the authentication.
|
||||
|
||||
@ -247,7 +643,7 @@ There are a couple of options to choose from when mapping user authorities:
|
||||
|
||||
|
||||
[[oauth2login-advanced-map-authorities-grantedauthoritiesmapper]]
|
||||
===== Using a GrantedAuthoritiesMapper
|
||||
====== Using a GrantedAuthoritiesMapper
|
||||
|
||||
Provide an implementation of `GrantedAuthoritiesMapper` and configure it as shown in the following example:
|
||||
|
||||
@ -322,7 +718,7 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
||||
[[oauth2login-advanced-map-authorities-oauth2userservice]]
|
||||
===== Delegation-based strategy with OAuth2UserService
|
||||
====== Delegation-based strategy with OAuth2UserService
|
||||
|
||||
This strategy is advanced compared to using a `GrantedAuthoritiesMapper`, however, it's also more flexible as it gives you access to the `OAuth2UserRequest` and `OAuth2User` (when using an OAuth 2.0 UserService) or `OidcUserRequest` and `OidcUser` (when using an OpenID Connect 1.0 UserService).
|
||||
|
||||
@ -373,7 +769,7 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
||||
[[oauth2login-advanced-custom-user]]
|
||||
==== Configuring a Custom OAuth2User
|
||||
===== Configuring a Custom OAuth2User
|
||||
|
||||
`CustomUserTypesOAuth2UserService` is an implementation of an `OAuth2UserService` that provides support for custom `OAuth2User` types.
|
||||
|
||||
@ -473,7 +869,7 @@ for https://developer.github.com/v3/users/#get-the-authenticated-user["Get the a
|
||||
|
||||
|
||||
[[oauth2login-advanced-oauth2-user-service]]
|
||||
==== OAuth 2.0 UserService
|
||||
===== OAuth 2.0 UserService
|
||||
|
||||
`DefaultOAuth2UserService` is an implementation of an `OAuth2UserService` that supports standard OAuth 2.0 Provider's.
|
||||
|
||||
@ -525,7 +921,7 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
||||
[[oauth2login-advanced-oidc-user-service]]
|
||||
==== OpenID Connect 1.0 UserService
|
||||
===== OpenID Connect 1.0 UserService
|
||||
|
||||
`OidcUserService` is an implementation of an `OAuth2UserService` that supports OpenID Connect 1.0 Provider's.
|
||||
|
||||
@ -558,3 +954,16 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[oauth2login-resources]]
|
||||
=== Additional Resources
|
||||
|
||||
The following additional resources describe advanced configuration options:
|
||||
|
||||
* <<oauth2login-advanced-login-page, OAuth 2.0 Login Page>>
|
||||
* <<oauth2login-advanced-redirection-endpoint, Redirection Endpoint>>
|
||||
* <<oauth2login-advanced-userinfo-endpoint, UserInfo Endpoint:>>
|
||||
** <<oauth2login-advanced-map-authorities, Mapping User Authorities>>
|
||||
** <<oauth2login-advanced-custom-user, Configuring a Custom OAuth2User>>
|
||||
** <<oauth2login-advanced-oauth2-user-service, OAuth 2.0 UserService>>
|
||||
** <<oauth2login-advanced-oidc-user-service, OpenID Connect 1.0 UserService>>
|
@ -1,3 +0,0 @@
|
||||
include::java-configuration.adoc[]
|
||||
|
||||
include::namespace.adoc[]
|
@ -1,829 +0,0 @@
|
||||
|
||||
[[jc]]
|
||||
= Java Configuration
|
||||
|
||||
General support for https://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java[Java Configuration] was added to Spring Framework in Spring 3.1.
|
||||
Since Spring Security 3.2 there has been Spring Security Java Configuration support which enables users to easily configure Spring Security without the use of any XML.
|
||||
|
||||
If you are familiar with the <<ns-config>> then you should find quite a few similarities between it and the Security Java Configuration support.
|
||||
|
||||
NOTE: Spring Security provides https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig[lots of sample applications] which demonstrate the use of Spring Security Java Configuration.
|
||||
|
||||
== Hello Web Security Java Configuration
|
||||
|
||||
The first step is to create our Spring Security Java Configuration.
|
||||
The configuration creates a Servlet Filter known as the `springSecurityFilterChain` which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, etc) within your application.
|
||||
You can find the most basic example of a Spring Security Java Configuration below:
|
||||
|
||||
[[jc-hello-wsca]]
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.security.config.annotation.authentication.builders.*;
|
||||
import org.springframework.security.config.annotation.web.configuration.*;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
There really isn't much to this configuration, but it does a lot.
|
||||
You can find a summary of the features below:
|
||||
|
||||
* Require authentication to every URL in your application
|
||||
* Generate a login form for you
|
||||
* Allow the user with the *Username* _user_ and the *Password* _password_ to authenticate with form based authentication
|
||||
* Allow the user to logout
|
||||
* https://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attack] prevention
|
||||
* https://en.wikipedia.org/wiki/Session_fixation[Session Fixation] protection
|
||||
* Security Header integration
|
||||
** https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HTTP Strict Transport Security] for secure requests
|
||||
** https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx[X-Content-Type-Options] integration
|
||||
** Cache Control (can be overridden later by your application to allow caching of your static resources)
|
||||
** https://msdn.microsoft.com/en-us/library/dd565647(v=vs.85).aspx[X-XSS-Protection] integration
|
||||
** X-Frame-Options integration to help prevent https://en.wikipedia.org/wiki/Clickjacking[Clickjacking]
|
||||
* Integrate with the following Servlet API methods
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()[HttpServletRequest#getRemoteUser()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal()[HttpServletRequest#getUserPrincipal()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)[HttpServletRequest#isUserInRole(java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String,%20java.lang.String)[HttpServletRequest#login(java.lang.String, java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#logout()[HttpServletRequest#logout()]
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer
|
||||
|
||||
The next step is to register the `springSecurityFilterChain` with the war.
|
||||
This can be done in Java Configuration with https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-container-config[Spring's WebApplicationInitializer support] in a Servlet 3.0+ environment.
|
||||
Not suprisingly, Spring Security provides a base class `AbstractSecurityWebApplicationInitializer` that will ensure the `springSecurityFilterChain` gets registered for you.
|
||||
The way in which we use `AbstractSecurityWebApplicationInitializer` differs depending on if we are already using Spring or if Spring Security is the only Spring component in our application.
|
||||
|
||||
* <<abstractsecuritywebapplicationinitializer-without-existing-spring>> - Use these instructions if you are not using Spring already
|
||||
* <<abstractsecuritywebapplicationinitializer-with-spring-mvc>> - Use these instructions if you are already using Spring
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer without Existing Spring
|
||||
|
||||
If you are not using Spring or Spring MVC, you will need to pass in the `WebSecurityConfig` into the superclass to ensure the configuration is picked up.
|
||||
You can find an example below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
public SecurityWebApplicationInitializer() {
|
||||
super(WebSecurityConfig.class);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The `SecurityWebApplicationInitializer` will do the following things:
|
||||
|
||||
* Automatically register the springSecurityFilterChain Filter for every URL in your application
|
||||
* Add a ContextLoaderListener that loads the <<jc-hello-wsca,WebSecurityConfig>>.
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer with Spring MVC
|
||||
|
||||
If we were using Spring elsewhere in our application we probably already had a `WebApplicationInitializer` that is loading our Spring Configuration.
|
||||
If we use the previous configuration we would get an error.
|
||||
Instead, we should register Spring Security with the existing `ApplicationContext`.
|
||||
For example, if we were using Spring MVC our `SecurityWebApplicationInitializer` would look something like the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
This would simply only register the springSecurityFilterChain Filter for every URL in your application.
|
||||
After that we would ensure that `WebSecurityConfig` was loaded in our existing ApplicationInitializer.
|
||||
For example, if we were using Spring MVC it would be added in the `getRootConfigClasses()`
|
||||
|
||||
[[message-web-application-inititializer-java]]
|
||||
[source,java]
|
||||
----
|
||||
public class MvcWebApplicationInitializer extends
|
||||
AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getRootConfigClasses() {
|
||||
return new Class[] { WebSecurityConfig.class };
|
||||
}
|
||||
|
||||
// ... other overrides ...
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-httpsecurity]]
|
||||
== HttpSecurity
|
||||
|
||||
Thus far our <<jc-hello-wsca,WebSecurityConfig>> only contains information about how to authenticate our users.
|
||||
How does Spring Security know that we want to require all users to be authenticated?
|
||||
How does Spring Security know we want to support form based authentication?
|
||||
Actually, there is an configuration class that is being invoked behind the scenes called `WebSecurityConfigurerAdapter`.
|
||||
It has a method called `configure` with the following default implementation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults())
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
----
|
||||
|
||||
The default configuration above:
|
||||
|
||||
* Ensures that any request to our application requires the user to be authenticated
|
||||
* Allows users to authenticate with form based login
|
||||
* Allows users to authenticate with HTTP Basic authentication
|
||||
|
||||
You will notice that this configuration is quite similar the XML Namespace configuration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<form-login />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
[[jc-form]]
|
||||
== Java Configuration and Form Login
|
||||
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs.
|
||||
Since Spring Security's default configuration does not explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.
|
||||
|
||||
While the automatically generated log in page is convenient to get up and running quickly, most applications will want to provide their own login page.
|
||||
When we want to change the default configuration, we can customize the `WebSecurityConfigurerAdapter` that we mentioned earlier by extending it like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
And then override the `configure` method as seen below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(formLogin ->
|
||||
formLogin
|
||||
.loginPage("/login") // <1>
|
||||
.permitAll() // <2>
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
<1> The updated configuration specifies the location of the log in page.
|
||||
<2> We must grant all users (i.e. unauthenticated users) access to our log in page.
|
||||
The `formLogin().permitAll()` method allows granting access to all users for all URLs associated with form based log in.
|
||||
|
||||
An example log in page implemented with JSPs for our current configuration can be seen below:
|
||||
|
||||
NOTE: The login page below represents our current configuration.
|
||||
We could easily update our configuration if some of the defaults do not meet our needs.
|
||||
|
||||
[source,html]
|
||||
----
|
||||
<c:url value="/login" var="loginUrl"/>
|
||||
<form action="${loginUrl}" method="post"> <1>
|
||||
<c:if test="${param.error != null}"> <2>
|
||||
<p>
|
||||
Invalid username and password.
|
||||
</p>
|
||||
</c:if>
|
||||
<c:if test="${param.logout != null}"> <3>
|
||||
<p>
|
||||
You have been logged out.
|
||||
</p>
|
||||
</c:if>
|
||||
<p>
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username"/> <4>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password"/> <5>
|
||||
</p>
|
||||
<input type="hidden" <6>
|
||||
name="${_csrf.parameterName}"
|
||||
value="${_csrf.token}"/>
|
||||
<button type="submit" class="btn">Log in</button>
|
||||
</form>
|
||||
----
|
||||
|
||||
<1> A POST to the `/login` URL will attempt to authenticate the user
|
||||
<2> If the query parameter `error` exists, authentication was attempted and failed
|
||||
<3> If the query parameter `logout` exists, the user was successfully logged out
|
||||
<4> The username must be present as the HTTP parameter named __username__
|
||||
<5> The password must be present as the HTTP parameter named __password__
|
||||
<6> We must <<csrf-include-csrf-token>> To learn more read the <<csrf>> section of the reference
|
||||
|
||||
[[jc-authorize-requests]]
|
||||
== Authorize Requests
|
||||
Our examples have only required users to be authenticated and have done so for every URL in our application.
|
||||
We can specify custom requirements for our URLs by adding multiple children to our `http.authorizeRequests()` method.
|
||||
For example:
|
||||
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests -> // <1>
|
||||
authorizeRequests
|
||||
.antMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
|
||||
.antMatchers("/admin/**").hasRole("ADMIN") // <3>
|
||||
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
|
||||
.anyRequest().authenticated() // <5>
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
}
|
||||
----
|
||||
|
||||
<1> There are multiple children to the `http.authorizeRequests()` method each matcher is considered in the order they were declared.
|
||||
<2> We specified multiple URL patterns that any user can access.
|
||||
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
|
||||
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
|
||||
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
|
||||
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
|
||||
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
|
||||
<5> Any URL that has not already been matched on only requires that the user be authenticated
|
||||
|
||||
[[jc-logout]]
|
||||
== Handling Logouts
|
||||
|
||||
When using the `{security-api-url}org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html[WebSecurityConfigurerAdapter]`, logout capabilities are automatically applied.
|
||||
The default is that accessing the URL `/logout` will log the user out by:
|
||||
|
||||
- Invalidating the HTTP Session
|
||||
- Cleaning up any RememberMe authentication that was configured
|
||||
- Clearing the `SecurityContextHolder`
|
||||
- Redirect to `/login?logout`
|
||||
|
||||
Similar to configuring login capabilities, however, you also have various options to further customize your logout requirements:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.logout(logout -> // <1>
|
||||
logout
|
||||
.logoutUrl("/my/logout") // <2>
|
||||
.logoutSuccessUrl("/my/index") // <3>
|
||||
.logoutSuccessHandler(logoutSuccessHandler) // <4>
|
||||
.invalidateHttpSession(true) // <5>
|
||||
.addLogoutHandler(logoutHandler) // <6>
|
||||
.deleteCookies(cookieNamesToClear) // <7>
|
||||
)
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
<1> Provides logout support.
|
||||
This is automatically applied when using `WebSecurityConfigurerAdapter`.
|
||||
<2> The URL that triggers log out to occur (default is `/logout`).
|
||||
If CSRF protection is enabled (default), then the request must also be a POST.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutUrl-java.lang.String-[JavaDoc].
|
||||
<3> The URL to redirect to after logout has occurred.
|
||||
The default is `/login?logout`.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutSuccessUrl-java.lang.String-[JavaDoc].
|
||||
<4> Let's you specify a custom `LogoutSuccessHandler`.
|
||||
If this is specified, `logoutSuccessUrl()` is ignored.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#logoutSuccessHandler-org.springframework.security.web.authentication.logout.LogoutSuccessHandler-[JavaDoc].
|
||||
<5> Specify whether to invalidate the `HttpSession` at the time of logout.
|
||||
This is *true* by default.
|
||||
Configures the `SecurityContextLogoutHandler` under the covers.
|
||||
For more information, please consult the {security-api-url}org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.html#invalidateHttpSession-boolean-[JavaDoc].
|
||||
<6> Adds a `LogoutHandler`.
|
||||
`SecurityContextLogoutHandler` is added as the last `LogoutHandler` by default.
|
||||
<7> Allows specifying the names of cookies to be removed on logout success.
|
||||
This is a shortcut for adding a `CookieClearingLogoutHandler` explicitly.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
Logouts can of course also be configured using the XML Namespace notation.
|
||||
Please see the documentation for the <<nsa-logout, logout element>> in the Spring Security XML Namespace section for further details.
|
||||
===
|
||||
|
||||
Generally, in order to customize logout functionality, you can add
|
||||
`{security-api-url}org/springframework/security/web/authentication/logout/LogoutHandler.html[LogoutHandler]`
|
||||
and/or
|
||||
`{security-api-url}org/springframework/security/web/authentication/logout/LogoutSuccessHandler.html[LogoutSuccessHandler]`
|
||||
implementations.
|
||||
For many common scenarios, these handlers are applied under the
|
||||
covers when using the fluent API.
|
||||
|
||||
[[jc-logout-handler]]
|
||||
=== LogoutHandler
|
||||
|
||||
Generally, `{security-api-url}org/springframework/security/web/authentication/logout/LogoutHandler.html[LogoutHandler]`
|
||||
implementations indicate classes that are able to participate in logout handling.
|
||||
They are expected to be invoked to perform necessary clean-up.
|
||||
As such they should
|
||||
not throw exceptions.
|
||||
Various implementations are provided:
|
||||
|
||||
- {security-api-url}org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.html[PersistentTokenBasedRememberMeServices]
|
||||
- {security-api-url}org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.html[TokenBasedRememberMeServices]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/CookieClearingLogoutHandler.html[CookieClearingLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/csrf/CsrfLogoutHandler.html[CsrfLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.html[SecurityContextLogoutHandler]
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/HeaderWriterLogoutHandler.html[HeaderWriterLogoutHandler]
|
||||
|
||||
Please see <<remember-me-impls>> for details.
|
||||
|
||||
Instead of providing `LogoutHandler` implementations directly, the fluent API also provides shortcuts that provide the respective `LogoutHandler` implementations under the covers.
|
||||
E.g. `deleteCookies()` allows specifying the names of one or more cookies to be removed on logout success.
|
||||
This is a shortcut compared to adding a `CookieClearingLogoutHandler`.
|
||||
|
||||
[[jc-logout-success-handler]]
|
||||
=== LogoutSuccessHandler
|
||||
|
||||
The `LogoutSuccessHandler` is called after a successful logout by the `LogoutFilter`, to handle e.g.
|
||||
redirection or forwarding to the appropriate destination.
|
||||
Note that the interface is almost the same as the `LogoutHandler` but may raise an exception.
|
||||
|
||||
The following implementations are provided:
|
||||
|
||||
- {security-api-url}org/springframework/security/web/authentication/logout/SimpleUrlLogoutSuccessHandler.html[SimpleUrlLogoutSuccessHandler]
|
||||
- HttpStatusReturningLogoutSuccessHandler
|
||||
|
||||
As mentioned above, you don't need to specify the `SimpleUrlLogoutSuccessHandler` directly.
|
||||
Instead, the fluent API provides a shortcut by setting the `logoutSuccessUrl()`.
|
||||
This will setup the `SimpleUrlLogoutSuccessHandler` under the covers.
|
||||
The provided URL will be redirected to after a logout has occurred.
|
||||
The default is `/login?logout`.
|
||||
|
||||
The `HttpStatusReturningLogoutSuccessHandler` can be interesting in REST API type scenarios.
|
||||
Instead of redirecting to a URL upon the successful logout, this `LogoutSuccessHandler` allows you to provide a plain HTTP status code to be returned.
|
||||
If not configured a status code 200 will be returned by default.
|
||||
|
||||
[[jc-logout-references]]
|
||||
=== Further Logout-Related References
|
||||
|
||||
- <<ns-logout, Logout Handling>>
|
||||
- <<test-logout, Testing Logout>>
|
||||
- <<servletapi-logout, HttpServletRequest.logout()>>
|
||||
- <<remember-me-impls>>
|
||||
- <<csrf-logout, Logging Out>> in section CSRF Caveats
|
||||
- Section <<cas-singlelogout, Single Logout>> (CAS protocol)
|
||||
- Documentation for the <<nsa-logout, logout element>> in the Spring Security XML Namespace section
|
||||
|
||||
|
||||
include::oauth2-client.adoc[]
|
||||
|
||||
include::oauth2-login.adoc[]
|
||||
|
||||
include::oauth2-resourceserver.adoc[]
|
||||
|
||||
[[jc-authentication-inmemory]]
|
||||
=== In-Memory Authentication
|
||||
|
||||
We have already seen an example of configuring in-memory authentication for a single user.
|
||||
Below is an example to configure multiple users:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build());
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
|
||||
return manager;
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-authentication-jdbc]]
|
||||
=== JDBC Authentication
|
||||
|
||||
You can find the updates to support JDBC based authentication.
|
||||
The example below assumes that you have already defined a `DataSource` within your application.
|
||||
The https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig/jdbc[jdbc-javaconfig] sample provides a complete example of using JDBC based authentication.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource)
|
||||
.withDefaultSchema()
|
||||
.withUser(users.username("user").password("password").roles("USER"))
|
||||
.withUser(users.username("admin").password("password").roles("USER","ADMIN"));
|
||||
}
|
||||
----
|
||||
|
||||
=== LDAP Authentication
|
||||
|
||||
You can find the updates to support LDAP based authentication.
|
||||
The https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig/ldap[ldap-javaconfig] sample provides a complete example of using LDAP based authentication.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchBase("ou=groups");
|
||||
}
|
||||
----
|
||||
|
||||
The example above uses the following LDIF and an embedded Apache DS LDAP instance.
|
||||
|
||||
.users.ldif
|
||||
----
|
||||
dn: ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: groups
|
||||
|
||||
dn: ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: people
|
||||
|
||||
dn: uid=admin,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Rod Johnson
|
||||
sn: Johnson
|
||||
uid: admin
|
||||
userPassword: password
|
||||
|
||||
dn: uid=user,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Dianne Emu
|
||||
sn: Emu
|
||||
uid: user
|
||||
userPassword: password
|
||||
|
||||
dn: cn=user,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: user
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
uniqueMember: uid=user,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=admin,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: admin
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
----
|
||||
|
||||
[[jc-authentication-authenticationprovider]]
|
||||
=== AuthenticationProvider
|
||||
|
||||
You can define custom authentication by exposing a custom `AuthenticationProvider` as a bean.
|
||||
For example, the following will customize authentication assuming that `SpringAuthenticationProvider` implements `AuthenticationProvider`:
|
||||
|
||||
NOTE: This is only used if the `AuthenticationManagerBuilder` has not been populated
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public SpringAuthenticationProvider springAuthenticationProvider() {
|
||||
return new SpringAuthenticationProvider();
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-authentication-userdetailsservice]]
|
||||
=== UserDetailsService
|
||||
|
||||
You can define custom authentication by exposing a custom `UserDetailsService` as a bean.
|
||||
For example, the following will customize authentication assuming that `SpringDataUserDetailsService` implements `UserDetailsService`:
|
||||
|
||||
NOTE: This is only used if the `AuthenticationManagerBuilder` has not been populated and no `AuthenticationProviderBean` is defined.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public SpringDataUserDetailsService springDataUserDetailsService() {
|
||||
return new SpringDataUserDetailsService();
|
||||
}
|
||||
----
|
||||
|
||||
You can also customize how passwords are encoded by exposing a `PasswordEncoder` as a bean.
|
||||
For example, if you use bcrypt you can add a bean definition as shown below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
----
|
||||
|
||||
== Multiple HttpSecurity
|
||||
|
||||
We can configure multiple HttpSecurity instances just as we can have multiple `<http>` blocks.
|
||||
The key is to extend the `WebSecurityConfigurerAdapter` multiple times.
|
||||
For example, the following is an example of having a different configuration for URL's that start with `/api/`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class MultiHttpSecurityConfig {
|
||||
@Bean <1>
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build());
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(1) <2>
|
||||
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.antMatcher("/api/**") <3>
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().hasRole("ADMIN")
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration <4>
|
||||
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<1> Configure Authentication as normal
|
||||
<2> Create an instance of `WebSecurityConfigurerAdapter` that contains `@Order` to specify which `WebSecurityConfigurerAdapter` should be considered first.
|
||||
<3> The `http.antMatcher` states that this `HttpSecurity` will only be applicable to URLs that start with `/api/`
|
||||
<4> Create another instance of `WebSecurityConfigurerAdapter`.
|
||||
If the URL does not start with `/api/` this configuration will be used.
|
||||
This configuration is considered after `ApiWebSecurityConfigurationAdapter` since it has an `@Order` value after `1` (no `@Order` defaults to last).
|
||||
|
||||
|
||||
[[jc-method]]
|
||||
== Method Security
|
||||
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods.
|
||||
It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation.
|
||||
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
|
||||
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
=== EnableGlobalMethodSecurity
|
||||
|
||||
We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.
|
||||
For example, the following would enable Spring Security's `@Secured` annotation.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
|
||||
Spring Security's native annotation support defines a set of attributes for the method.
|
||||
These will be passed to the AccessDecisionManager for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@Secured("ROLE_TELLER")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Support for JSR-250 annotations can be enabled using
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations.
|
||||
To use the new expression-based syntax, you would use
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
and the equivalent Java code would be
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@PreAuthorize("hasAuthority('ROLE_TELLER')")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
=== GlobalMethodSecurityConfiguration
|
||||
|
||||
Sometimes you may need to perform operations that are more complicated than are possible with the `@EnableGlobalMethodSecurity` annotation allow.
|
||||
For these instances, you can extend the `GlobalMethodSecurityConfiguration` ensuring that the `@EnableGlobalMethodSecurity` annotation is present on your subclass.
|
||||
For example, if you wanted to provide a custom `MethodSecurityExpressionHandler`, you could use the following configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
// ... create and return custom MethodSecurityExpressionHandler ...
|
||||
return expressionHandler;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
For additional information about methods that can be overridden, refer to the `GlobalMethodSecurityConfiguration` Javadoc.
|
||||
|
||||
== Post Processing Configured Objects
|
||||
|
||||
Spring Security's Java Configuration does not expose every property of every object that it configures.
|
||||
This simplifies the configuration for a majority of users.
|
||||
Afterall, if every property was exposed, users could use standard bean configuration.
|
||||
|
||||
While there are good reasons to not directly expose every property, users may still need more advanced configuration options.
|
||||
To address this Spring Security introduces the concept of an `ObjectPostProcessor` which can be used to modify or replace many of the Object instances created by the Java Configuration.
|
||||
For example, if you wanted to configure the `filterSecurityPublishAuthorizationSuccess` property on `FilterSecurityInterceptor` you could use the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
|
||||
public <O extends FilterSecurityInterceptor> O postProcess(
|
||||
O fsi) {
|
||||
fsi.setPublishAuthorizationSuccess(true);
|
||||
return fsi;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-custom-dsls]]
|
||||
== Custom DSLs
|
||||
|
||||
You can provide your own custom DSLs in Spring Security.
|
||||
For example, you might have something that looks like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
|
||||
private boolean flag;
|
||||
|
||||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
// any method that adds another configurer
|
||||
// must be done in the init method
|
||||
http.csrf().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
|
||||
// here we lookup from the ApplicationContext. You can also just create a new instance.
|
||||
MyFilter myFilter = context.getBean(MyFilter.class);
|
||||
myFilter.setFlag(flag);
|
||||
http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
public MyCustomDsl flag(boolean value) {
|
||||
this.flag = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static MyCustomDsl customDsl() {
|
||||
return new MyCustomDsl();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: This is actually how methods like `HttpSecurity.authorizeRequests()` are implemented.
|
||||
|
||||
The custom DSL can then be used like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl())
|
||||
.flag(true)
|
||||
.and()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The code is invoked in the following order:
|
||||
|
||||
* Code in `Config`s configure method is invoked
|
||||
* Code in `MyCustomDsl`s init method is invoked
|
||||
* Code in `MyCustomDsl`s configure method is invoked
|
||||
|
||||
If you want, you can have `WebSecurityConfiguerAdapter` add `MyCustomDsl` by default by using `SpringFactories`.
|
||||
For example, you would create a resource on the classpath named `META-INF/spring.factories` with the following contents:
|
||||
|
||||
.META-INF/spring.factories
|
||||
----
|
||||
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl
|
||||
----
|
||||
|
||||
Users wishing to disable the default can do so explicitly.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl()).disable()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
@ -1,912 +0,0 @@
|
||||
|
||||
[[ns-config]]
|
||||
= Security Namespace Configuration
|
||||
|
||||
|
||||
== Introduction
|
||||
Namespace configuration has been available since version 2.0 of the Spring Framework.
|
||||
It allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema.
|
||||
You can find more information in the Spring https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/[Reference Documentation].
|
||||
A namespace element can be used simply to allow a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax which more closely matches the problem domain and hides the underlying complexity from the user.
|
||||
A simple element may conceal the fact that multiple beans and processing steps are being added to the application context.
|
||||
For example, adding the following element from the security namespace to an application context will start up an embedded LDAP server for testing use within the application:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<security:ldap-server />
|
||||
----
|
||||
|
||||
This is much simpler than wiring up the equivalent Apache Directory Server beans.
|
||||
The most common alternative configuration requirements are supported by attributes on the `ldap-server` element and the user is isolated from worrying about which beans they need to create and what the bean property names are.
|
||||
footnote:[You can find out more about the use of the `ldap-server` element in the chapter on pass:specialcharacters,macros[<<ldap>>].].
|
||||
Use of a good XML editor while editing the application context file should provide information on the attributes and elements that are available.
|
||||
We would recommend that you try out the https://spring.io/tools/sts[Spring Tool Suite] as it has special features for working with standard Spring namespaces.
|
||||
|
||||
|
||||
To start using the security namespace in your application context, you need to have the `spring-security-config` jar on your classpath.
|
||||
Then all you need to do is add the schema declaration to your application context file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans>
|
||||
----
|
||||
|
||||
In many of the examples you will see (and in the sample applications), we will often use "security" as the default namespace rather than "beans", which means we can omit the prefix on all the security namespace elements, making the content easier to read.
|
||||
You may also want to do this if you have your application context divided up into separate files and have most of your security configuration in one of them.
|
||||
Your security application context file would then start like this
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans:beans>
|
||||
----
|
||||
|
||||
We'll assume this syntax is being used from now on in this chapter.
|
||||
|
||||
|
||||
=== Design of the Namespace
|
||||
The namespace is designed to capture the most common uses of the framework and provide a simplified and concise syntax for enabling them within an application.
|
||||
The design is based around the large-scale dependencies within the framework, and can be divided up into the following areas:
|
||||
|
||||
* __Web/HTTP Security__ - the most complex part.
|
||||
Sets up the filters and related service beans used to apply the framework authentication mechanisms, to secure URLs, render login and error pages and much more.
|
||||
|
||||
* __Business Object (Method) Security__ - options for securing the service layer.
|
||||
|
||||
* __AuthenticationManager__ - handles authentication requests from other parts of the framework.
|
||||
|
||||
* __AccessDecisionManager__ - provides access decisions for web and method security.
|
||||
A default one will be registered, but you can also choose to use a custom one, declared using normal Spring bean syntax.
|
||||
|
||||
* __AuthenticationProvider__s - mechanisms against which the authentication manager authenticates users.
|
||||
The namespace provides supports for several standard options and also a means of adding custom beans declared using a traditional syntax.
|
||||
|
||||
* __UserDetailsService__ - closely related to authentication providers, but often also required by other beans.
|
||||
|
||||
We'll see how to configure these in the following sections.
|
||||
|
||||
[[ns-getting-started]]
|
||||
== Getting Started with Security Namespace Configuration
|
||||
In this section, we'll look at how you can build up a namespace configuration to use some of the main features of the framework.
|
||||
Let's assume you initially want to get up and running as quickly as possible and add authentication support and access control to an existing web application, with a few test logins.
|
||||
Then we'll look at how to change over to authenticating against a database or other security repository.
|
||||
In later sections we'll introduce more advanced namespace configuration options.
|
||||
|
||||
[[ns-web-xml]]
|
||||
=== web.xml Configuration
|
||||
The first thing you need to do is add the following filter declaration to your `web.xml` file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
----
|
||||
|
||||
This provides a hook into the Spring Security web infrastructure.
|
||||
`DelegatingFilterProxy` is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in your application context.
|
||||
In this case, the bean is named "springSecurityFilterChain", which is an internal infrastructure bean created by the namespace to handle web security.
|
||||
Note that you should not use this bean name yourself.
|
||||
Once you've added this to your `web.xml`, you're ready to start editing your application context file.
|
||||
Web security services are configured using the `<http>` element.
|
||||
|
||||
[[ns-minimal]]
|
||||
=== A Minimal <http> Configuration
|
||||
All you need to enable web security to begin with is
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="hasRole('USER')" />
|
||||
<form-login />
|
||||
<logout />
|
||||
</http>
|
||||
----
|
||||
|
||||
Which says that we want all URLs within our application to be secured, requiring the role `ROLE_USER` to access them, we want to log in to the application using a form with username and password, and that we want a logout URL registered which will allow us to log out of the application.
|
||||
`<http>` element is the parent for all web-related namespace functionality.
|
||||
The `<intercept-url>` element defines a `pattern` which is matched against the URLs of incoming requests using an ant path style syntax footnote:[See the section on pass:specialcharacters,macros[<<request-matching>>] in the Web Application Infrastructure chapter for more details on how matches are actually performed.].
|
||||
You can also use regular-expression matching as an alternative (see the namespace appendix for more details).
|
||||
The `access` attribute defines the access requirements for requests matching the given pattern.
|
||||
With the default configuration, this is typically a comma-separated list of roles, one of which a user must have to be allowed to make the request.
|
||||
The prefix "ROLE_" is a marker which indicates that a simple comparison with the user's authorities should be made.
|
||||
In other words, a normal role-based check should be used.
|
||||
Access-control in Spring Security is not limited to the use of simple roles (hence the use of the prefix to differentiate between different types of security attributes).
|
||||
We'll see later how the interpretation can vary footnote:[The interpretation of the comma-separated values in the `access` attribute depends on the implementation of the <<ns-access-manager,AccessDecisionManager>> which is used.].
|
||||
In Spring Security 3.0, the attribute can also be populated with an pass:specialcharacters,macros[<<el-access,EL expression>>].
|
||||
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
|
||||
You can use multiple `<intercept-url>` elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used.
|
||||
So you must put the most specific matches at the top.
|
||||
You can also add a `method` attribute to limit the match to a particular HTTP method (`GET`, `POST`, `PUT` etc.).
|
||||
|
||||
===
|
||||
|
||||
To add some users, you can define a set of test data directly in the namespace:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
|
||||
NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
|
||||
in samples easier. Normally passwords should be hashed using BCrypt -->
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
This is an example of a secure way of storing the same passwords.
|
||||
The password is prefixed with `{bcrypt}` to instruct `DelegatingPasswordEncoder`, which supports any configured `PasswordEncoder` for matching, that the passwords are hashed using BCrypt:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
|
||||
authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
|
||||
authorities="ROLE_USER" />
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[subs="quotes"]
|
||||
****
|
||||
If you are familiar with pre-namespace versions of the framework, you can probably already guess roughly what's going on here.
|
||||
The `<http>` element is responsible for creating a `FilterChainProxy` and the filter beans which it uses.
|
||||
Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined.
|
||||
|
||||
The `<authentication-provider>` element creates a `DaoAuthenticationProvider` bean and the `<user-service>` element creates an `InMemoryDaoImpl`.
|
||||
All `authentication-provider` elements must be children of the `<authentication-manager>` element, which creates a `ProviderManager` and registers the authentication providers with it.
|
||||
You can find more detailed information on the beans that are created in the <<appendix-namespace,namespace appendix>>.
|
||||
It's worth cross-checking this if you want to start understanding what the important classes in the framework are and how they are used, particularly if you want to customise things later.
|
||||
****
|
||||
|
||||
The configuration above defines two users, their passwords and their roles within the application (which will be used for access control).
|
||||
It is also possible to load user information from a standard properties file using the `properties` attribute on `user-service`.
|
||||
See the section on <<core-services-in-memory-service,in-memory authentication>> for more details on the file format.
|
||||
Using the `<authentication-provider>` element means that the user information will be used by the authentication manager to process authentication requests.
|
||||
You can have multiple `<authentication-provider>` elements to define different authentication sources and each will be consulted in turn.
|
||||
|
||||
At this point you should be able to start up your application and you will be required to log in to proceed.
|
||||
Try it out, or try experimenting with the "tutorial" sample application that comes with the project.
|
||||
|
||||
|
||||
[[ns-form-and-basic]]
|
||||
=== Form and Basic Login Options
|
||||
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs.
|
||||
In fact, since we didn't explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.
|
||||
However, the namespace offers plenty of support to allow you to customize these options.
|
||||
For example, if you want to supply your own login page, you could use:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<form-login login-page='/login.jsp'/>
|
||||
</http>
|
||||
----
|
||||
|
||||
Also note that we've added an extra `intercept-url` element to say that any requests for the login page should be available to anonymous users footnote:[See the chapter on pass:specialcharacters,macros[<<anonymous>>]] and also the <<authz-authenticated-voter,AuthenticatedVoter>> class for more details on how the value `IS_AUTHENTICATED_ANONYMOUSLY` is processed.].
|
||||
Otherwise the request would be matched by the pattern /** and it wouldn't be possible to access the login page itself!
|
||||
This is a common configuration error and will result in an infinite loop in the application.
|
||||
Spring Security will emit a warning in the log if your login page appears to be secured.
|
||||
It is also possible to have all requests matching a particular pattern bypass the security filter chain completely, by defining a separate `http` element for the pattern like this:
|
||||
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http pattern="/css/**" security="none"/>
|
||||
<http pattern="/login.jsp*" security="none"/>
|
||||
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<form-login login-page='/login.jsp'/>
|
||||
</http>
|
||||
----
|
||||
|
||||
From Spring Security 3.1 it is now possible to use multiple `http` elements to define separate security filter chain configurations for different request patterns.
|
||||
If the `pattern` attribute is omitted from an `http` element, it matches all requests.
|
||||
Creating an unsecured pattern is a simple example of this syntax, where the pattern is mapped to an empty filter chain footnote:[The use of multiple `<http>` elements is an important feature, allowing the namespace to simultaneously support both stateful and stateless paths within the same application, for example.
|
||||
The previous syntax, using the attribute `filters="none"` on an `intercept-url` element is incompatible with this change and is no longer supported in 3.1.].
|
||||
We'll look at this new syntax in more detail in the chapter on the <<filter-chains-with-ns,Security Filter Chain>>.
|
||||
|
||||
It's important to realise that these unsecured requests will be completely oblivious to any Spring Security web-related configuration or additional attributes such as `requires-channel`, so you will not be able to access information on the current user or call secured methods during the request.
|
||||
Use `access='IS_AUTHENTICATED_ANONYMOUSLY'` as an alternative if you still want the security filter chain to be applied.
|
||||
|
||||
If you want to use basic authentication instead of form login, then change the configuration to
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource.
|
||||
Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page.
|
||||
|
||||
[[ns-form-target]]
|
||||
==== Setting a Default Post-Login Destination
|
||||
If a form login isn't prompted by an attempt to access a protected resource, the `default-target-url` option comes into play.
|
||||
This is the URL the user will be taken to after successfully logging in, and defaults to "/".
|
||||
You can also configure things so that the user __always__ ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the `always-use-default-target` attribute to "true".
|
||||
This is useful if your application always requires that the user starts at a "home" page, for example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http pattern="/login.htm*" security="none"/>
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern='/**' access='ROLE_USER' />
|
||||
<form-login login-page='/login.htm' default-target-url='/home.htm'
|
||||
always-use-default-target='true' />
|
||||
</http>
|
||||
----
|
||||
|
||||
For even more control over the destination, you can use the `authentication-success-handler-ref` attribute as an alternative to `default-target-url`.
|
||||
The referenced bean should be an instance of `AuthenticationSuccessHandler`.
|
||||
You'll find more on this in the <<form-login-flow-handling,Core Filters>> chapter and also in the namespace appendix, as well as information on how to customize the flow when authentication fails.
|
||||
|
||||
[[ns-logout]]
|
||||
=== Logout Handling
|
||||
The `logout` element adds support for logging out by navigating to a particular URL.
|
||||
The default logout URL is `/logout`, but you can set it to something else using the `logout-url` attribute.
|
||||
More information on other available attributes may be found in the namespace appendix.
|
||||
|
||||
[[ns-auth-providers]]
|
||||
=== Using other Authentication Providers
|
||||
In practice you will need a more scalable source of user information than a few names added to the application context file.
|
||||
Most likely you will want to store your user information in something like a database or an LDAP server.
|
||||
LDAP namespace configuration is dealt with in the <<ldap,LDAP chapter>>, so we won't cover it here.
|
||||
If you have a custom implementation of Spring Security's `UserDetailsService`, called "myUserDetailsService" in your application context, then you can authenticate against this using
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider user-service-ref='myUserDetailsService'/>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
If you want to use a database, then you can use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<jdbc-user-service data-source-ref="securityDataSource"/>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
Where "securityDataSource" is the name of a `DataSource` bean in the application context, pointing at a database containing the standard Spring Security <<user-schema,user data tables>>.
|
||||
Alternatively, you could configure a Spring Security `JdbcDaoImpl` bean and point at that using the `user-service-ref` attribute:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider user-service-ref='myUserDetailsService'/>
|
||||
</authentication-manager>
|
||||
|
||||
<beans:bean id="myUserDetailsService"
|
||||
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
|
||||
<beans:property name="dataSource" ref="dataSource"/>
|
||||
</beans:bean>
|
||||
----
|
||||
|
||||
You can also use standard `AuthenticationProvider` beans as follows
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider ref='myAuthenticationProvider'/>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
where `myAuthenticationProvider` is the name of a bean in your application context which implements `AuthenticationProvider`.
|
||||
You can use multiple `authentication-provider` elements, in which case the providers will be queried in the order they are declared.
|
||||
See <<ns-auth-manager>> for more information on how the Spring Security `AuthenticationManager` is configured using the namespace.
|
||||
|
||||
[[ns-password-encoder]]
|
||||
==== Adding a Password Encoder
|
||||
Passwords should always be encoded using a secure hashing algorithm designed for the purpose (not a standard algorithm like SHA or MD5).
|
||||
This is supported by the `<password-encoder>` element.
|
||||
With bcrypt encoded passwords, the original authentication provider configuration would look like this:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans:bean name="bcryptEncoder"
|
||||
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<password-encoder ref="bcryptEncoder"/>
|
||||
<user-service>
|
||||
<user name="jimi" password="$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
|
||||
authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
|
||||
authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
|
||||
----
|
||||
|
||||
|
||||
|
||||
bcrypt is a good choice for most cases, unless you have a legacy system which forces you to use a different algorithm.
|
||||
If you are using a simple hashing algorithm or, even worse, storing plain text passwords, then you should consider migrating to a more secure option like bcrypt.
|
||||
|
||||
[[ns-web-advanced]]
|
||||
== Advanced Web Features
|
||||
|
||||
[[ns-remember-me]]
|
||||
=== Remember-Me Authentication
|
||||
See the separate <<remember-me,Remember-Me chapter>> for information on remember-me namespace configuration.
|
||||
|
||||
[[ns-requires-channel]]
|
||||
=== Adding HTTP/HTTPS Channel Security
|
||||
If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the `requires-channel` attribute on `<intercept-url>`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
|
||||
...
|
||||
</http>
|
||||
----
|
||||
|
||||
With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL footnote:[For more details on how channel-processing is implemented, see the Javadoc for `ChannelProcessingFilter` and related classes.].
|
||||
The available options are "http", "https" or "any".
|
||||
Using the value "any" means that either HTTP or HTTPS can be used.
|
||||
|
||||
If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<port-mappings>
|
||||
<port-mapping http="9080" https="9443"/>
|
||||
</port-mappings>
|
||||
</http>
|
||||
----
|
||||
|
||||
Note that in order to be truly secure, an application should not use HTTP at all or switch between HTTP and HTTPS.
|
||||
It should start in HTTPS (with the user entering an HTTPS URL) and use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.
|
||||
|
||||
[[ns-session-mgmt]]
|
||||
=== Session Management
|
||||
|
||||
==== Detecting Timeouts
|
||||
You can configure Spring Security to detect the submission of an invalid session ID and redirect the user to an appropriate URL.
|
||||
This is achieved through the `session-management` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management invalid-session-url="/invalidSession.htm" />
|
||||
</http>
|
||||
----
|
||||
|
||||
Note that if you use this mechanism to detect session timeouts, it may falsely report an error if the user logs out and then logs back in without closing the browser.
|
||||
This is because the session cookie is not cleared when you invalidate the session and will be resubmitted even if the user has logged out.
|
||||
You may be able to explicitly delete the JSESSIONID cookie on logging out, for example by using the following syntax in the logout handler:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<logout delete-cookies="JSESSIONID" />
|
||||
</http>
|
||||
----
|
||||
|
||||
Unfortunately this can't be guaranteed to work with every servlet container, so you will need to test it in your environment
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
If you are running your application behind a proxy, you may also be able to remove the session cookie by configuring the proxy server.
|
||||
For example, using Apache HTTPD's mod_headers, the following directive would delete the `JSESSIONID` cookie by expiring it in the response to a logout request (assuming the application is deployed under the path `/tutorial`):
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<LocationMatch "/tutorial/logout">
|
||||
Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
|
||||
</LocationMatch>
|
||||
----
|
||||
===
|
||||
|
||||
|
||||
[[ns-concurrent-sessions]]
|
||||
==== Concurrent Session Control
|
||||
If you wish to place constraints on a single user's ability to log in to your application, Spring Security supports this out of the box with the following simple additions.
|
||||
First you need to add the following listener to your `web.xml` file to keep Spring Security updated about session lifecycle events:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.springframework.security.web.session.HttpSessionEventPublisher
|
||||
</listener-class>
|
||||
</listener>
|
||||
----
|
||||
|
||||
Then add the following lines to your application context:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management>
|
||||
<concurrency-control max-sessions="1" />
|
||||
</session-management>
|
||||
</http>
|
||||
----
|
||||
|
||||
This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated.
|
||||
Often you would prefer to prevent a second login, in which case you can use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
...
|
||||
<session-management>
|
||||
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
|
||||
</session-management>
|
||||
</http>
|
||||
----
|
||||
|
||||
The second login will then be rejected.
|
||||
By "rejected", we mean that the user will be sent to the `authentication-failure-url` if form-based login is being used.
|
||||
If the second authentication takes place through another non-interactive mechanism, such as "remember-me", an "unauthorized" (401) error will be sent to the client.
|
||||
If instead you want to use an error page, you can add the attribute `session-authentication-error-url` to the `session-management` element.
|
||||
|
||||
If you are using a customized authentication filter for form-based login, then you have to configure concurrent session control support explicitly.
|
||||
More details can be found in the <<session-mgmt,Session Management chapter>>.
|
||||
|
||||
[[ns-session-fixation]]
|
||||
==== Session Fixation Attack Protection
|
||||
https://en.wikipedia.org/wiki/Session_fixation[Session fixation] attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example).
|
||||
Spring Security protects against this automatically by creating a new session or otherwise changing the session ID when a user logs in.
|
||||
If you don't require this protection, or it conflicts with some other requirement, you can control the behavior using the `session-fixation-protection` attribute on `<session-management>`, which has four options
|
||||
|
||||
* `none` - Don't do anything.
|
||||
The original session will be retained.
|
||||
|
||||
* `newSession` - Create a new "clean" session, without copying the existing session data (Spring Security-related attributes will still be copied).
|
||||
|
||||
* `migrateSession` - Create a new session and copy all existing session attributes to the new session.
|
||||
This is the default in Servlet 3.0 or older containers.
|
||||
|
||||
* `changeSessionId` - Do not create a new session.
|
||||
Instead, use the session fixation protection provided by the Servlet container (`HttpServletRequest#changeSessionId()`).
|
||||
This option is only available in Servlet 3.1 (Java EE 7) and newer containers.
|
||||
Specifying it in older containers will result in an exception.
|
||||
This is the default in Servlet 3.1 and newer containers.
|
||||
|
||||
|
||||
When session fixation protection occurs, it results in a `SessionFixationProtectionEvent` being published in the application context.
|
||||
If you use `changeSessionId`, this protection will __also__ result in any `javax.servlet.http.HttpSessionIdListener` s being notified, so use caution if your code listens for both events.
|
||||
See the <<session-mgmt,Session Management>> chapter for additional information.
|
||||
|
||||
|
||||
[[ns-openid]]
|
||||
=== OpenID Support
|
||||
The namespace supports https://openid.net/[OpenID] login either instead of, or in addition to normal form-based login, with a simple change:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<openid-login />
|
||||
</http>
|
||||
----
|
||||
|
||||
You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory `<user-service>`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<user name="https://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
|
||||
----
|
||||
|
||||
You should be able to login using the `myopenid.com` site to authenticate.
|
||||
It is also possible to select a specific `UserDetailsService` bean for use OpenID by setting the `user-service-ref` attribute on the `openid-login` element.
|
||||
See the previous section on <<ns-auth-providers,authentication providers>> for more information.
|
||||
Note that we have omitted the password attribute from the above user configuration, since this set of user data is only being used to load the authorities for the user.
|
||||
A random password will be generated internally, preventing you from accidentally using this user data as an authentication source elsewhere in your configuration.
|
||||
|
||||
|
||||
==== Attribute Exchange
|
||||
Support for OpenID https://openid.net/specs/openid-attribute-exchange-1_0.html[attribute exchange].
|
||||
As an example, the following configuration would attempt to retrieve the email and full name from the OpenID provider, for use by the application:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<openid-login>
|
||||
<attribute-exchange>
|
||||
<openid-attribute name="email" type="https://axschema.org/contact/email" required="true"/>
|
||||
<openid-attribute name="name" type="https://axschema.org/namePerson"/>
|
||||
</attribute-exchange>
|
||||
</openid-login>
|
||||
----
|
||||
|
||||
The "type" of each OpenID attribute is a URI, determined by a particular schema, in this case https://axschema.org/[https://axschema.org/].
|
||||
If an attribute must be retrieved for successful authentication, the `required` attribute can be set.
|
||||
The exact schema and attributes supported will depend on your OpenID provider.
|
||||
The attribute values are returned as part of the authentication process and can be accessed afterwards using the following code:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
OpenIDAuthenticationToken token =
|
||||
(OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
|
||||
List<OpenIDAttribute> attributes = token.getAttributes();
|
||||
----
|
||||
|
||||
The `OpenIDAttribute` contains the attribute type and the retrieved value (or values in the case of multi-valued attributes).
|
||||
We'll see more about how the `SecurityContextHolder` class is used when we look at core Spring Security components in the <<core-components,technical overview>> chapter.
|
||||
Multiple attribute exchange configurations are also be supported, if you wish to use multiple identity providers.
|
||||
You can supply multiple `attribute-exchange` elements, using an `identifier-matcher` attribute on each.
|
||||
This contains a regular expression which will be matched against the OpenID identifier supplied by the user.
|
||||
See the OpenID sample application in the codebase for an example configuration, providing different attribute lists for the Google, Yahoo and MyOpenID providers.
|
||||
|
||||
|
||||
[[ns-headers]]
|
||||
=== Response Headers
|
||||
For additional information on how to customize the headers element refer to the <<headers>> section of the reference.
|
||||
|
||||
|
||||
[[ns-custom-filters]]
|
||||
=== Adding in Your Own Filters
|
||||
If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services.
|
||||
You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example).
|
||||
Or you might want to use a customized version of a standard namespace filter, such as the `UsernamePasswordAuthenticationFilter` which is created by the `<form-login>` element, taking advantage of some of the extra configuration options which are available by using the bean explicitly.
|
||||
How can you do this with namespace configuration, since the filter chain is not directly exposed?
|
||||
|
||||
The order of the filters is always strictly enforced when using the namespace.
|
||||
When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context.
|
||||
In version 3.0+ the sorting is now done at the bean metadata level, before the classes have been instantiated.
|
||||
This has implications for how you add your own filters to the stack as the entire filter list must be known during the parsing of the `<http>` element, so the syntax has changed slightly in 3.0.
|
||||
===
|
||||
|
||||
The filters, aliases and namespace elements/attributes which create the filters are shown in <<filter-stack>>.
|
||||
The filters are listed in the order in which they occur in the filter chain.
|
||||
|
||||
[[filter-stack]]
|
||||
.Standard Filter Aliases and Ordering
|
||||
|===
|
||||
| Alias | Filter Class | Namespace Element or Attribute
|
||||
|
||||
| CHANNEL_FILTER
|
||||
| `ChannelProcessingFilter`
|
||||
| `http/intercept-url@requires-channel`
|
||||
|
||||
| SECURITY_CONTEXT_FILTER
|
||||
| `SecurityContextPersistenceFilter`
|
||||
| `http`
|
||||
|
||||
| CONCURRENT_SESSION_FILTER
|
||||
| `ConcurrentSessionFilter`
|
||||
| `session-management/concurrency-control`
|
||||
|
||||
| HEADERS_FILTER
|
||||
| `HeaderWriterFilter`
|
||||
| `http/headers`
|
||||
|
||||
| CSRF_FILTER
|
||||
| `CsrfFilter`
|
||||
| `http/csrf`
|
||||
|
||||
| LOGOUT_FILTER
|
||||
| `LogoutFilter`
|
||||
| `http/logout`
|
||||
|
||||
| X509_FILTER
|
||||
| `X509AuthenticationFilter`
|
||||
| `http/x509`
|
||||
|
||||
| PRE_AUTH_FILTER
|
||||
| `AbstractPreAuthenticatedProcessingFilter` Subclasses
|
||||
| N/A
|
||||
|
||||
| CAS_FILTER
|
||||
| `CasAuthenticationFilter`
|
||||
| N/A
|
||||
|
||||
| FORM_LOGIN_FILTER
|
||||
| `UsernamePasswordAuthenticationFilter`
|
||||
| `http/form-login`
|
||||
|
||||
| BASIC_AUTH_FILTER
|
||||
| `BasicAuthenticationFilter`
|
||||
| `http/http-basic`
|
||||
|
||||
| SERVLET_API_SUPPORT_FILTER
|
||||
| `SecurityContextHolderAwareRequestFilter`
|
||||
| `http/@servlet-api-provision`
|
||||
|
||||
| JAAS_API_SUPPORT_FILTER
|
||||
| `JaasApiIntegrationFilter`
|
||||
| `http/@jaas-api-provision`
|
||||
|
||||
| REMEMBER_ME_FILTER
|
||||
| `RememberMeAuthenticationFilter`
|
||||
| `http/remember-me`
|
||||
|
||||
| ANONYMOUS_FILTER
|
||||
| `AnonymousAuthenticationFilter`
|
||||
| `http/anonymous`
|
||||
|
||||
| SESSION_MANAGEMENT_FILTER
|
||||
| `SessionManagementFilter`
|
||||
| `session-management`
|
||||
|
||||
| EXCEPTION_TRANSLATION_FILTER
|
||||
| `ExceptionTranslationFilter`
|
||||
| `http`
|
||||
|
||||
| FILTER_SECURITY_INTERCEPTOR
|
||||
| `FilterSecurityInterceptor`
|
||||
| `http`
|
||||
|
||||
| SWITCH_USER_FILTER
|
||||
| `SwitchUserFilter`
|
||||
| N/A
|
||||
|===
|
||||
|
||||
You can add your own filter to the stack, using the `custom-filter` element and one of these names to specify the position your filter should appear at:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
|
||||
</http>
|
||||
|
||||
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
|
||||
----
|
||||
|
||||
You can also use the `after` or `before` attributes if you want your filter to be inserted before or after another filter in the stack.
|
||||
The names "FIRST" and "LAST" can be used with the `position` attribute to indicate that you want your filter to appear before or after the entire stack, respectively.
|
||||
|
||||
.Avoiding filter position conflicts
|
||||
[TIP]
|
||||
===
|
||||
|
||||
If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake.
|
||||
Remove any elements which create filters whose functionality you want to replace.
|
||||
|
||||
Note that you can't replace filters which are created by the use of the `<http>` element itself - `SecurityContextPersistenceFilter`, `ExceptionTranslationFilter` or `FilterSecurityInterceptor`.
|
||||
Some other filters are added by default, but you can disable them.
|
||||
An `AnonymousAuthenticationFilter` is added by default and unless you have <<ns-session-fixation,session-fixation protection>> disabled, a `SessionManagementFilter` will also be added to the filter chain.
|
||||
|
||||
===
|
||||
|
||||
If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too.
|
||||
|
||||
|
||||
[[ns-entry-point-ref]]
|
||||
==== Setting a Custom AuthenticationEntryPoint
|
||||
If you aren't using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we've just seen.
|
||||
The corresponding `AuthenticationEntryPoint` can be set using the `entry-point-ref` attribute on the `<http>` element.
|
||||
|
||||
The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax.
|
||||
If you aren't familiar with authentication entry points, they are discussed in the <<tech-intro-auth-entry-point,technical overview>> chapter.
|
||||
|
||||
|
||||
[[ns-method-security]]
|
||||
== Method Security
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods.
|
||||
It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation.
|
||||
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
|
||||
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
|
||||
[[ns-global-method]]
|
||||
=== The <global-method-security> Element
|
||||
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context.
|
||||
You should only declare one `<global-method-security>` element.
|
||||
The following declaration would enable support for Spring Security's `@Secured`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security secured-annotations="enabled" />
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly.
|
||||
Spring Security's native annotation support defines a set of attributes for the method.
|
||||
These will be passed to the `AccessDecisionManager` for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@Secured("ROLE_TELLER")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Support for JSR-250 annotations can be enabled using
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security jsr250-annotations="enabled" />
|
||||
----
|
||||
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations.
|
||||
To use the new expression-based syntax, you would use
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security pre-post-annotations="enabled" />
|
||||
----
|
||||
|
||||
and the equivalent Java code would be
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account readAccount(Long id);
|
||||
|
||||
@PreAuthorize("isAnonymous()")
|
||||
public Account[] findAccounts();
|
||||
|
||||
@PreAuthorize("hasAuthority('ROLE_TELLER')")
|
||||
public Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
Expression-based annotations are a good choice if you need to define simple rules that go beyond checking the role names against the user's list of authorities.
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
The annotated methods will only be secured for instances which are defined as Spring beans (in the same application context in which method-security is enabled).
|
||||
If you want to secure instances which are not created by Spring (using the `new` operator, for example) then you need to use AspectJ.
|
||||
===
|
||||
|
||||
[NOTE]
|
||||
===
|
||||
You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behaviour will not be well-defined otherwise.
|
||||
If two annotations are found which apply to a particular method, then only one of them will be applied.
|
||||
===
|
||||
|
||||
[[ns-protect-pointcut]]
|
||||
==== Adding Security Pointcuts using protect-pointcut
|
||||
|
||||
The use of `protect-pointcut` is particularly powerful, as it allows you to apply security to many beans with only a simple declaration.
|
||||
Consider the following example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security>
|
||||
<protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"
|
||||
access="ROLE_USER"/>
|
||||
</global-method-security>
|
||||
----
|
||||
|
||||
This will protect all methods on beans declared in the application context whose classes are in the `com.mycompany` package and whose class names end in "Service".
|
||||
Only users with the `ROLE_USER` role will be able to invoke these methods.
|
||||
As with URL matching, the most specific matches must come first in the list of pointcuts, as the first matching expression will be used.
|
||||
Security annotations take precedence over pointcuts.
|
||||
|
||||
[[ns-access-manager]]
|
||||
== The Default AccessDecisionManager
|
||||
This section assumes you have some knowledge of the underlying architecture for access-control within Spring Security.
|
||||
If you don't you can skip it and come back to it later, as this section is only really relevant for people who need to do some customization in order to use more than simple role-based security.
|
||||
|
||||
When you use a namespace configuration, a default instance of `AccessDecisionManager` is automatically registered for you and will be used for making access decisions for method invocations and web URL access, based on the access attributes you specify in your `intercept-url` and `protect-pointcut` declarations (and in annotations if you are using annotation secured methods).
|
||||
|
||||
The default strategy is to use an `AffirmativeBased` `AccessDecisionManager` with a `RoleVoter` and an `AuthenticatedVoter`.
|
||||
You can find out more about these in the chapter on <<authz-arch,authorization>>.
|
||||
|
||||
|
||||
[[ns-custom-access-mgr]]
|
||||
=== Customizing the AccessDecisionManager
|
||||
If you need to use a more complicated access control strategy then it is easy to set an alternative for both method and web security.
|
||||
|
||||
For method security, you do this by setting the `access-decision-manager-ref` attribute on `global-method-security` to the `id` of the appropriate `AccessDecisionManager` bean in the application context:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</global-method-security>
|
||||
----
|
||||
|
||||
The syntax for web security is the same, but on the `http` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</http>
|
||||
----
|
||||
|
||||
[[ns-auth-manager]]
|
||||
== The Authentication Manager and the Namespace
|
||||
The main interface which provides authentication services in Spring Security is the `AuthenticationManager`.
|
||||
This is usually an instance of Spring Security's `ProviderManager` class, which you may already be familiar with if you've used the framework before.
|
||||
If not, it will be covered later, in the <<tech-intro-authentication,technical overview chapter>>.
|
||||
The bean instance is registered using the `authentication-manager` namespace element.
|
||||
You can't use a custom `AuthenticationManager` if you are using either HTTP or method security through the namespace, but this should not be a problem as you have full control over the `AuthenticationProvider` s that are used.
|
||||
|
||||
You may want to register additional `AuthenticationProvider` beans with the `ProviderManager` and you can do this using the `<authentication-provider>` element with the `ref` attribute, where the value of the attribute is the name of the provider bean you want to add.
|
||||
For example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider ref="casAuthenticationProvider"/>
|
||||
</authentication-manager>
|
||||
|
||||
<bean id="casAuthenticationProvider"
|
||||
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
|
||||
...
|
||||
</bean>
|
||||
----
|
||||
|
||||
Another common requirement is that another bean in the context may require a reference to the `AuthenticationManager`.
|
||||
You can easily register an alias for the `AuthenticationManager` and use this name elsewhere in your application context.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<security:authentication-manager alias="authenticationManager">
|
||||
...
|
||||
</security:authentication-manager>
|
||||
|
||||
<bean id="customizedFormLoginFilter"
|
||||
class="com.somecompany.security.web.CustomFormLoginFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
...
|
||||
</bean>
|
||||
----
|
@ -1,409 +0,0 @@
|
||||
[[oauth2login]]
|
||||
== OAuth 2.0 Login
|
||||
|
||||
The OAuth 2.0 Login feature provides an application with the capability to have users log in to the application by using their existing account at an OAuth 2.0 Provider (e.g. GitHub) or OpenID Connect 1.0 Provider (such as Google).
|
||||
OAuth 2.0 Login implements the use cases: "Login with Google" or "Login with GitHub".
|
||||
|
||||
NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0].
|
||||
|
||||
|
||||
[[oauth2login-sample-boot]]
|
||||
=== Spring Boot 2.x Sample
|
||||
|
||||
Spring Boot 2.x brings full auto-configuration capabilities for OAuth 2.0 Login.
|
||||
|
||||
This section shows how to configure the {gh-samples-url}/boot/oauth2login[*OAuth 2.0 Login sample*] using _Google_ as the _Authentication Provider_ and covers the following topics:
|
||||
|
||||
* <<oauth2login-sample-initial-setup,Initial setup>>
|
||||
* <<oauth2login-sample-redirect-uri,Setting the redirect URI>>
|
||||
* <<oauth2login-sample-application-config,Configure application.yml>>
|
||||
* <<oauth2login-sample-boot-application,Boot up the application>>
|
||||
|
||||
|
||||
[[oauth2login-sample-initial-setup]]
|
||||
==== Initial setup
|
||||
|
||||
To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials.
|
||||
|
||||
NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified].
|
||||
|
||||
Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the section, "Setting up OAuth 2.0".
|
||||
|
||||
After completing the "Obtain OAuth 2.0 credentials" instructions, you should have a new OAuth Client with credentials consisting of a Client ID and a Client Secret.
|
||||
|
||||
|
||||
[[oauth2login-sample-redirect-uri]]
|
||||
==== Setting the redirect URI
|
||||
|
||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google and have granted access to the OAuth Client _(<<oauth2login-sample-initial-setup,created in the previous step>>)_ on the Consent page.
|
||||
|
||||
In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`.
|
||||
|
||||
TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`.
|
||||
The *_registrationId_* is a unique identifier for the <<oauth2Client-client-registration,ClientRegistration>>.
|
||||
|
||||
|
||||
[[oauth2login-sample-application-config]]
|
||||
==== Configure application.yml
|
||||
|
||||
Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_.
|
||||
To do so:
|
||||
|
||||
. Go to `application.yml` and set the following configuration:
|
||||
+
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration: <1>
|
||||
google: <2>
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
+
|
||||
.OAuth Client properties
|
||||
====
|
||||
<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties.
|
||||
<2> Following the base property prefix is the ID for the <<oauth2Client-client-registration,ClientRegistration>>, such as google.
|
||||
====
|
||||
|
||||
. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier.
|
||||
|
||||
|
||||
[[oauth2login-sample-boot-application]]
|
||||
==== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.x sample and go to `http://localhost:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
||||
|
||||
Click on the Google link, and you are then redirected to Google for authentication.
|
||||
|
||||
After authenticating with your Google account credentials, the next page presented to you is the Consent screen.
|
||||
The Consent screen asks you to either allow or deny access to the OAuth Client you created earlier.
|
||||
Click *Allow* to authorize the OAuth Client to access your email address and basic profile information.
|
||||
|
||||
At this point, the OAuth Client retrieves your email address and basic profile information from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session.
|
||||
|
||||
|
||||
[[oauth2login-boot-property-mappings]]
|
||||
=== Spring Boot 2.x Property Mappings
|
||||
|
||||
The following table outlines the mapping of the Spring Boot 2.x OAuth Client properties to the <<oauth2Client-client-registration,ClientRegistration>> properties.
|
||||
|
||||
|===
|
||||
|Spring Boot 2.x |ClientRegistration
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_`
|
||||
|`registrationId`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-id`
|
||||
|`clientId`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-secret`
|
||||
|`clientSecret`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-authentication-method`
|
||||
|`clientAuthenticationMethod`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.authorization-grant-type`
|
||||
|`authorizationGrantType`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.redirect-uri`
|
||||
|`redirectUriTemplate`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.scope`
|
||||
|`scopes`
|
||||
|
||||
|`spring.security.oauth2.client.registration._[registrationId]_.client-name`
|
||||
|`clientName`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.authorization-uri`
|
||||
|`providerDetails.authorizationUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.token-uri`
|
||||
|`providerDetails.tokenUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.jwk-set-uri`
|
||||
|`providerDetails.jwkSetUri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.user-info-uri`
|
||||
|`providerDetails.userInfoEndpoint.uri`
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.user-info-authentication-method`
|
||||
|`providerDetails.userInfoEndpoint.authenticationMethod`
|
||||
|
||||
|
||||
|`spring.security.oauth2.client.provider._[providerId]_.userNameAttribute`
|
||||
|`providerDetails.userInfoEndpoint.userNameAttributeName`
|
||||
|===
|
||||
|
||||
|
||||
[[oauth2login-common-oauth2-provider]]
|
||||
=== CommonOAuth2Provider
|
||||
|
||||
`CommonOAuth2Provider` pre-defines a set of default client properties for a number of well known providers: Google, GitHub, Facebook, and Okta.
|
||||
|
||||
For example, the `authorization-uri`, `token-uri`, and `user-info-uri` do not change often for a Provider.
|
||||
Therefore, it makes sense to provide default values in order to reduce the required configuration.
|
||||
|
||||
As demonstrated previously, when we <<oauth2login-sample-application-config,configured a Google client>>, only the `client-id` and `client-secret` properties are required.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
google:
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
|
||||
[TIP]
|
||||
The auto-defaulting of client properties works seamlessly here because the `registrationId` (`google`) matches the `GOOGLE` `enum` (case-insensitive) in `CommonOAuth2Provider`.
|
||||
|
||||
For cases where you may want to specify a different `registrationId`, such as `google-login`, you can still leverage auto-defaulting of client properties by configuring the `provider` property.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
google-login: <1>
|
||||
provider: google <2>
|
||||
client-id: google-client-id
|
||||
client-secret: google-client-secret
|
||||
----
|
||||
<1> The `registrationId` is set to `google-login`.
|
||||
<2> The `provider` property is set to `google`, which will leverage the auto-defaulting of client properties set in `CommonOAuth2Provider.GOOGLE.getBuilder()`.
|
||||
|
||||
|
||||
[[oauth2login-custom-provider-properties]]
|
||||
=== Configuring Custom Provider Properties
|
||||
|
||||
There are some OAuth 2.0 Providers that support multi-tenancy, which results in different protocol endpoints for each tenant (or sub-domain).
|
||||
|
||||
For example, an OAuth Client registered with Okta is assigned to a specific sub-domain and have their own protocol endpoints.
|
||||
|
||||
For these cases, Spring Boot 2.x provides the following base property for configuring custom provider properties: `spring.security.oauth2.client.provider._[providerId]_`.
|
||||
|
||||
The following listing shows an example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
okta:
|
||||
client-id: okta-client-id
|
||||
client-secret: okta-client-secret
|
||||
provider:
|
||||
okta: <1>
|
||||
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
|
||||
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
|
||||
user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
|
||||
user-name-attribute: sub
|
||||
jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
|
||||
----
|
||||
|
||||
<1> The base property (`spring.security.oauth2.client.provider.okta`) allows for custom configuration of protocol endpoint locations.
|
||||
|
||||
|
||||
[[oauth2login-override-boot-autoconfig]]
|
||||
=== Overriding Spring Boot 2.x Auto-configuration
|
||||
|
||||
The Spring Boot 2.x auto-configuration class for OAuth Client support is `OAuth2ClientAutoConfiguration`.
|
||||
|
||||
It performs the following tasks:
|
||||
|
||||
* Registers a `ClientRegistrationRepository` `@Bean` composed of `ClientRegistration`(s) from the configured OAuth Client properties.
|
||||
* Provides a `WebSecurityConfigurerAdapter` `@Configuration` and enables OAuth 2.0 Login through `httpSecurity.oauth2Login()`.
|
||||
|
||||
If you need to override the auto-configuration based on your specific requirements, you may do so in the following ways:
|
||||
|
||||
* <<oauth2login-register-clientregistrationrepository-bean,Register a ClientRegistrationRepository @Bean>>
|
||||
* <<oauth2login-provide-websecurityconfigureradapter,Provide a WebSecurityConfigurerAdapter>>
|
||||
* <<oauth2login-completely-override-autoconfiguration,Completely Override the Auto-configuration>>
|
||||
|
||||
|
||||
[[oauth2login-register-clientregistrationrepository-bean]]
|
||||
==== Register a ClientRegistrationRepository @Bean
|
||||
|
||||
The following example shows how to register a `ClientRegistrationRepository` `@Bean`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return ClientRegistration.withRegistrationId("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
|
||||
.scope("openid", "profile", "email", "address", "phone")
|
||||
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
|
||||
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
|
||||
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
.userNameAttributeName(IdTokenClaimNames.SUB)
|
||||
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
|
||||
.clientName("Google")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-provide-websecurityconfigureradapter]]
|
||||
==== Provide a WebSecurityConfigurerAdapter
|
||||
|
||||
The following example shows how to provide a `WebSecurityConfigurerAdapter` with `@EnableWebSecurity` and enable OAuth 2.0 login through `httpSecurity.oauth2Login()`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-completely-override-autoconfiguration]]
|
||||
==== Completely Override the Auto-configuration
|
||||
|
||||
The following example shows how to completely override the auto-configuration by registering a `ClientRegistrationRepository` `@Bean` and providing a `WebSecurityConfigurerAdapter`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@EnableWebSecurity
|
||||
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return ClientRegistration.withRegistrationId("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
|
||||
.scope("openid", "profile", "email", "address", "phone")
|
||||
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
|
||||
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
|
||||
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
.userNameAttributeName(IdTokenClaimNames.SUB)
|
||||
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
|
||||
.clientName("Google")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-javaconfig-wo-boot]]
|
||||
=== Java Configuration without Spring Boot 2.x
|
||||
|
||||
If you are not able to use Spring Boot 2.x and would like to configure one of the pre-defined providers in `CommonOAuth2Provider` (for example, Google), apply the following configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class OAuth2LoginConfig {
|
||||
|
||||
@EnableWebSecurity
|
||||
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorizeRequests ->
|
||||
authorizeRequests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2Login(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientService authorizedClientService(
|
||||
ClientRegistrationRepository clientRegistrationRepository) {
|
||||
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientRepository authorizedClientRepository(
|
||||
OAuth2AuthorizedClientService authorizedClientService) {
|
||||
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
|
||||
}
|
||||
|
||||
private ClientRegistration googleClientRegistration() {
|
||||
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[oauth2login-resources]]
|
||||
=== Additional Resources
|
||||
|
||||
The following additional resources describe advanced configuration options:
|
||||
|
||||
* <<oauth2login-advanced-login-page, OAuth 2.0 Login Page>>
|
||||
* <<oauth2login-advanced-redirection-endpoint, Redirection Endpoint>>
|
||||
* <<oauth2login-advanced-userinfo-endpoint, UserInfo Endpoint:>>
|
||||
** <<oauth2login-advanced-map-authorities, Mapping User Authorities>>
|
||||
** <<oauth2login-advanced-custom-user, Configuring a Custom OAuth2User>>
|
||||
** <<oauth2login-advanced-oauth2-user-service, OAuth 2.0 UserService>>
|
||||
** <<oauth2login-advanced-oidc-user-service, OpenID Connect 1.0 UserService>>
|
@ -1,28 +0,0 @@
|
||||
[[web-app-security]]
|
||||
= Web Application Security
|
||||
Most Spring Security users will be using the framework in applications which make user of HTTP and the Servlet API.
|
||||
In this part, we'll take a look at how Spring Security provides authentication and access-control features for the web layer of an application.
|
||||
We'll look behind the facade of the namespace and see which classes and interfaces are actually assembled to provide web-layer security.
|
||||
In some situations it is necessary to use traditional bean configuration to provide full control over the configuration, so we'll also see how to configure these classes directly without the namespace.
|
||||
|
||||
include::security-filter-chain.adoc[]
|
||||
|
||||
include::core-filters.adoc[]
|
||||
|
||||
include::servlet-api.adoc[]
|
||||
|
||||
include::basic.adoc[]
|
||||
|
||||
include::rememberme.adoc[]
|
||||
|
||||
include::csrf.adoc[]
|
||||
|
||||
include::cors.adoc[]
|
||||
|
||||
include::headers.adoc[]
|
||||
|
||||
include::session-management.adoc[]
|
||||
|
||||
include::anonymous.adoc[]
|
||||
|
||||
include::websocket.adoc[]
|
Loading…
x
Reference in New Issue
Block a user