瀏覽代碼

Extract architecture subsections

Issue: gh-2567
Rob Winch 7 年之前
父節點
當前提交
cf4272ff64

+ 178 - 0
docs/manual/src/docs/asciidoc/_includes/architecture/core-services.adoc

@@ -0,0 +1,178 @@
+
+[[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`.
+These crop up regularly throughout the remainder of this document so it's important you know how they are configured and how they operate.
+
+
+[[core-services-authentication-manager]]
+=== The AuthenticationManager, ProviderManager and AuthenticationProvider
+The `AuthenticationManager` is just an interface, so the implementation can be anything we choose, but how does it work in practice? What if we need to check multiple authentication databases or a combination of different authentication services such as a database and an LDAP server?
+
+The default implementation in Spring Security is called `ProviderManager` and rather than handling the authentication request itself, it delegates to a list of configured `AuthenticationProvider` s, each of which is queried in turn to see if it can perform the authentication.
+Each provider will either throw an exception or return a fully populated `Authentication` object.
+Remember our good friends, `UserDetails` and `UserDetailsService`? If not, head back to the previous chapter and refresh your memory.
+The most common approach to verifying an authentication request is to load the corresponding `UserDetails` and check the loaded password against the one that has been entered by the user.
+This is the approach used by the `DaoAuthenticationProvider` (see below).
+The loaded `UserDetails` object - and particularly the `GrantedAuthority` s it contains - will be used when building the fully populated `Authentication` object which is returned from a successful authentication and stored in the `SecurityContext`.
+
+If you are using the namespace, an instance of `ProviderManager` is created and maintained internally, and you add providers to it by using the namespace authentication provider elements (see <<ns-auth-manager,the namespace chapter>>).
+In this case, you should not declare a `ProviderManager` bean in your application context.
+However, if you are not using the namespace then you would declare it like so:
+
+[source,xml]
+----
+
+<bean id="authenticationManager"
+		class="org.springframework.security.authentication.ProviderManager">
+	<constructor-arg>
+		<list>
+			<ref local="daoAuthenticationProvider"/>
+			<ref local="anonymousAuthenticationProvider"/>
+			<ref local="ldapAuthenticationProvider"/>
+		</list>
+	</constructor-arg>
+</bean>
+----
+
+In the above example we have three providers.
+They are tried in the order shown (which is implied by the use of a `List`), with each provider able to attempt authentication, or skip authentication by simply returning `null`.
+If all implementations return null, the `ProviderManager` will throw a `ProviderNotFoundException`.
+If you're interested in learning more about chaining providers, please refer to the `ProviderManager` Javadoc.
+
+Authentication mechanisms such as a web form-login processing filter are injected with a reference to the `ProviderManager` and will call it to handle their authentication requests.
+The providers you require will sometimes be interchangeable with the authentication mechanisms, while at other times they will depend on a specific authentication mechanism.
+For example, `DaoAuthenticationProvider` and `LdapAuthenticationProvider` are compatible with any mechanism which submits a simple username/password authentication request and so will work with form-based logins or HTTP Basic authentication.
+On the other hand, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of `AuthenticationProvider`.
+An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be authenticated by a `CasAuthenticationProvider`.
+You needn't be too concerned about this, because if you forget to register a suitable provider, you'll simply receive a `ProviderNotFoundException` when an attempt to authenticate is made.
+
+
+[[core-services-erasing-credentials]]
+==== Erasing Credentials on Successful Authentication
+By default (from Spring Security 3.1 onwards) the `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
+This prevents information like passwords being retained longer than necessary.
+
+This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
+If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
+You need to take this into account if you are using a cache.
+An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
+Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
+See the Javadoc for more information.
+
+
+[[core-services-dao-provider]]
+==== DaoAuthenticationProvider
+The simplest `AuthenticationProvider` implemented by Spring Security is `DaoAuthenticationProvider`, which is also one of the earliest supported by the framework.
+It leverages a `UserDetailsService` (as a DAO) in order to lookup the username, password and `GrantedAuthority` s.
+It authenticates the user simply by comparing the password submitted in a `UsernamePasswordAuthenticationToken` against the one loaded by the `UserDetailsService`.
+Configuring the provider is quite simple:
+
+[source,xml]
+----
+
+<bean id="daoAuthenticationProvider"
+	class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
+<property name="userDetailsService" ref="inMemoryDaoImpl"/>
+<property name="passwordEncoder" ref="passwordEncoder"/>
+</bean>
+----
+
+The `PasswordEncoder` is optional.
+A `PasswordEncoder` provides encoding and decoding of passwords presented in the `UserDetails` object that is returned from the configured `UserDetailsService`.
+This will be discussed in more detail <<core-services-password-encoding,below>>.
+
+
+=== UserDetailsService Implementations
+As mentioned in the earlier in this reference guide, most authentication providers take advantage of the `UserDetails` and `UserDetailsService` interfaces.
+Recall that the contract for `UserDetailsService` is a single method:
+
+[source,java]
+----
+UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
+----
+
+The returned `UserDetails` is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled.
+Most authentication providers will use a `UserDetailsService`, even if the username and password are not actually used as part of the authentication decision.
+They may use the returned `UserDetails` object just for its `GrantedAuthority` information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials.
+
+Given `UserDetailsService` is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice.
+Having said that, Spring Security does include a couple of useful base implementations, which we'll look at below.
+
+
+[[core-services-in-memory-service]]
+==== In-Memory Authentication
+Is easy to use create a custom `UserDetailsService` implementation that extracts information from a persistence engine of choice, but many applications do not require such complexity.
+This is particularly true if you're building a prototype application or just starting integrating Spring Security, when you don't really want to spend time configuring databases or writing `UserDetailsService` implementations.
+For this sort of situation, a simple option is to use the `user-service` element from the security <<ns-minimal,namespace>>:
+
+[source,xml]
+----
+<user-service id="userDetailsService">
+<!-- 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>
+----
+
+
+This also supports the use of an external properties file:
+
+[source,xml]
+----
+<user-service id="userDetailsService" properties="users.properties"/>
+----
+
+The properties file should contain entries in the form
+
+[source,txt]
+----
+username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
+----
+
+For example
+
+[source,txt]
+----
+jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
+bob=bobspassword,ROLE_USER,enabled
+----
+
+[[core-services-jdbc-user-service]]
+==== JdbcDaoImpl
+Spring Security also includes a `UserDetailsService` that can obtain authentication information from a JDBC data source.
+Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to store user details.
+If your application does use an ORM tool, you might prefer to write a custom `UserDetailsService` to reuse the mapping files you've probably already created.
+Returning to `JdbcDaoImpl`, an example configuration is shown below:
+
+[source,xml]
+----
+<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
+<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
+<property name="username" value="sa"/>
+<property name="password" value=""/>
+</bean>
+
+<bean id="userDetailsService"
+	class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
+<property name="dataSource" ref="dataSource"/>
+</bean>
+----
+
+You can use different relational database management systems by modifying the `DriverManagerDataSource` shown above.
+You can also use a global data source obtained from JNDI, as with any other Spring configuration.
+
+===== Authority Groups
+By default, `JdbcDaoImpl` loads the authorities for a single user with the assumption that the authorities are mapped directly to users (see the <<appendix-schema,database schema appendix>>).
+An alternative approach is to partition the authorities into groups and assign groups to the user.
+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[]
+

+ 9 - 0
docs/manual/src/docs/asciidoc/_includes/architecture/index.adoc

@@ -0,0 +1,9 @@
+[[overall-architecture]]
+= Architecture and Implementation
+Once you are familiar with setting up and running some namespace-configuration based applications, you may wish to develop more of an understanding of how the framework actually works behind the namespace facade.
+Like most software, Spring Security has certain central interfaces, classes and conceptual abstractions that are commonly used throughout the framework.
+In this part of the reference guide we will look at some of these and see how they work together to support authentication and access-control within Spring Security.
+
+include::technical-overview.adoc[]
+
+include::core-services.adoc[]

+ 0 - 0
docs/manual/src/docs/asciidoc/_includes/jackson.adoc → docs/manual/src/docs/asciidoc/_includes/architecture/jackson.adoc


+ 0 - 0
docs/manual/src/docs/asciidoc/_includes/password-encoder.adoc → docs/manual/src/docs/asciidoc/_includes/architecture/password-encoder.adoc


+ 0 - 185
docs/manual/src/docs/asciidoc/_includes/architecture.adoc → docs/manual/src/docs/asciidoc/_includes/architecture/technical-overview.adoc

@@ -1,9 +1,3 @@
-[[overall-architecture]]
-= Architecture and Implementation
-Once you are familiar with setting up and running some namespace-configuration based applications, you may wish to develop more of an understanding of how the framework actually works behind the namespace facade.
-Like most software, Spring Security has certain central interfaces, classes and conceptual abstractions that are commonly used throughout the framework.
-In this part of the reference guide we will look at some of these and see how they work together to support authentication and access-control within Spring Security.
-
 
 [[technical-overview]]
 == Technical Overview
@@ -466,182 +460,3 @@ You can either do this in a filter yourself (which must come before the Spring S
 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.
-
-
-[[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`.
-These crop up regularly throughout the remainder of this document so it's important you know how they are configured and how they operate.
-
-
-[[core-services-authentication-manager]]
-=== The AuthenticationManager, ProviderManager and AuthenticationProvider
-The `AuthenticationManager` is just an interface, so the implementation can be anything we choose, but how does it work in practice? What if we need to check multiple authentication databases or a combination of different authentication services such as a database and an LDAP server?
-
-The default implementation in Spring Security is called `ProviderManager` and rather than handling the authentication request itself, it delegates to a list of configured `AuthenticationProvider` s, each of which is queried in turn to see if it can perform the authentication.
-Each provider will either throw an exception or return a fully populated `Authentication` object.
-Remember our good friends, `UserDetails` and `UserDetailsService`? If not, head back to the previous chapter and refresh your memory.
-The most common approach to verifying an authentication request is to load the corresponding `UserDetails` and check the loaded password against the one that has been entered by the user.
-This is the approach used by the `DaoAuthenticationProvider` (see below).
-The loaded `UserDetails` object - and particularly the `GrantedAuthority` s it contains - will be used when building the fully populated `Authentication` object which is returned from a successful authentication and stored in the `SecurityContext`.
-
-If you are using the namespace, an instance of `ProviderManager` is created and maintained internally, and you add providers to it by using the namespace authentication provider elements (see <<ns-auth-manager,the namespace chapter>>).
-In this case, you should not declare a `ProviderManager` bean in your application context.
-However, if you are not using the namespace then you would declare it like so:
-
-[source,xml]
-----
-
-<bean id="authenticationManager"
-		class="org.springframework.security.authentication.ProviderManager">
-	<constructor-arg>
-		<list>
-			<ref local="daoAuthenticationProvider"/>
-			<ref local="anonymousAuthenticationProvider"/>
-			<ref local="ldapAuthenticationProvider"/>
-		</list>
-	</constructor-arg>
-</bean>
-----
-
-In the above example we have three providers.
-They are tried in the order shown (which is implied by the use of a `List`), with each provider able to attempt authentication, or skip authentication by simply returning `null`.
-If all implementations return null, the `ProviderManager` will throw a `ProviderNotFoundException`.
-If you're interested in learning more about chaining providers, please refer to the `ProviderManager` Javadoc.
-
-Authentication mechanisms such as a web form-login processing filter are injected with a reference to the `ProviderManager` and will call it to handle their authentication requests.
-The providers you require will sometimes be interchangeable with the authentication mechanisms, while at other times they will depend on a specific authentication mechanism.
-For example, `DaoAuthenticationProvider` and `LdapAuthenticationProvider` are compatible with any mechanism which submits a simple username/password authentication request and so will work with form-based logins or HTTP Basic authentication.
-On the other hand, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of `AuthenticationProvider`.
-An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be authenticated by a `CasAuthenticationProvider`.
-You needn't be too concerned about this, because if you forget to register a suitable provider, you'll simply receive a `ProviderNotFoundException` when an attempt to authenticate is made.
-
-
-[[core-services-erasing-credentials]]
-==== Erasing Credentials on Successful Authentication
-By default (from Spring Security 3.1 onwards) the `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
-This prevents information like passwords being retained longer than necessary.
-
-This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
-If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
-You need to take this into account if you are using a cache.
-An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
-Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
-See the Javadoc for more information.
-
-
-[[core-services-dao-provider]]
-==== DaoAuthenticationProvider
-The simplest `AuthenticationProvider` implemented by Spring Security is `DaoAuthenticationProvider`, which is also one of the earliest supported by the framework.
-It leverages a `UserDetailsService` (as a DAO) in order to lookup the username, password and `GrantedAuthority` s.
-It authenticates the user simply by comparing the password submitted in a `UsernamePasswordAuthenticationToken` against the one loaded by the `UserDetailsService`.
-Configuring the provider is quite simple:
-
-[source,xml]
-----
-
-<bean id="daoAuthenticationProvider"
-	class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-<property name="userDetailsService" ref="inMemoryDaoImpl"/>
-<property name="passwordEncoder" ref="passwordEncoder"/>
-</bean>
-----
-
-The `PasswordEncoder` is optional.
-A `PasswordEncoder` provides encoding and decoding of passwords presented in the `UserDetails` object that is returned from the configured `UserDetailsService`.
-This will be discussed in more detail <<core-services-password-encoding,below>>.
-
-
-=== UserDetailsService Implementations
-As mentioned in the earlier in this reference guide, most authentication providers take advantage of the `UserDetails` and `UserDetailsService` interfaces.
-Recall that the contract for `UserDetailsService` is a single method:
-
-[source,java]
-----
-UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
-----
-
-The returned `UserDetails` is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled.
-Most authentication providers will use a `UserDetailsService`, even if the username and password are not actually used as part of the authentication decision.
-They may use the returned `UserDetails` object just for its `GrantedAuthority` information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials.
-
-Given `UserDetailsService` is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice.
-Having said that, Spring Security does include a couple of useful base implementations, which we'll look at below.
-
-
-[[core-services-in-memory-service]]
-==== In-Memory Authentication
-Is easy to use create a custom `UserDetailsService` implementation that extracts information from a persistence engine of choice, but many applications do not require such complexity.
-This is particularly true if you're building a prototype application or just starting integrating Spring Security, when you don't really want to spend time configuring databases or writing `UserDetailsService` implementations.
-For this sort of situation, a simple option is to use the `user-service` element from the security <<ns-minimal,namespace>>:
-
-[source,xml]
-----
-<user-service id="userDetailsService">
-<!-- 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>
-----
-
-
-This also supports the use of an external properties file:
-
-[source,xml]
-----
-<user-service id="userDetailsService" properties="users.properties"/>
-----
-
-The properties file should contain entries in the form
-
-[source,txt]
-----
-username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
-----
-
-For example
-
-[source,txt]
-----
-jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
-bob=bobspassword,ROLE_USER,enabled
-----
-
-[[core-services-jdbc-user-service]]
-==== JdbcDaoImpl
-Spring Security also includes a `UserDetailsService` that can obtain authentication information from a JDBC data source.
-Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to store user details.
-If your application does use an ORM tool, you might prefer to write a custom `UserDetailsService` to reuse the mapping files you've probably already created.
-Returning to `JdbcDaoImpl`, an example configuration is shown below:
-
-[source,xml]
-----
-<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
-<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
-<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
-<property name="username" value="sa"/>
-<property name="password" value=""/>
-</bean>
-
-<bean id="userDetailsService"
-	class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
-<property name="dataSource" ref="dataSource"/>
-</bean>
-----
-
-You can use different relational database management systems by modifying the `DriverManagerDataSource` shown above.
-You can also use a global data source obtained from JNDI, as with any other Spring configuration.
-
-===== Authority Groups
-By default, `JdbcDaoImpl` loads the authorities for a single user with the assumption that the authorities are mapped directly to users (see the <<appendix-schema,database schema appendix>>).
-An alternative approach is to partition the authorities into groups and assign groups to the user.
-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 - 1
docs/manual/src/docs/asciidoc/index.adoc

@@ -8,7 +8,7 @@ It is the de-facto standard for securing Spring-based applications.
 
 include::{include-dir}/preface/index.adoc[]
 
-include::{include-dir}/architecture.adoc[]
+include::{include-dir}/architecture/index.adoc[]
 
 include::{include-dir}/test.adoc[]