Show
9.1 In-Memory AuthenticationWe have already seen an example of configuring in-memory authentication for a single user. Below is an example to configure multiple users: @Bean public UserDetailsService userDetailsService() throws Exception { 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; } 9.2 JDBC AuthenticationYou can find the updates to support JDBC based authentication. The example below assumes that you have already defined a @Autowired private DataSource dataSource; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 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")); } 9.3 LDAP Authentication9.3.1 OverviewLDAP is often used by organizations as a central repository for user information and as an authentication service. It can also be used to store the role information for application users. There are many different scenarios for how an LDAP server may be configured so Spring Security’s LDAP provider is fully configurable. It uses separate strategy interfaces for authentication and role retrieval and provides default implementations which can be configured to handle a wide range of situations. You should be familiar with LDAP before trying to use it with Spring Security. The following link provides a good introduction to the concepts involved and a guide to setting up a directory using the free LDAP server OpenLDAP: http://www.zytrax.com/books/ldap/. Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We don’t use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so some familiarity with that project may be useful if you plan on adding your own customizations. When using LDAP authentication, it is important to ensure that you configure LDAP connection pooling properly. If you are unfamiliar with how to do this, you can refer to the Java LDAP documentation. 9.3.2 Using LDAP with Spring SecurityLDAP authentication in Spring Security can be roughly divided into the following stages.
The exception is when the LDAP directory is just being used to retrieve user information and authenticate against it locally. This may not be possible as directories are often set up with limited read access for attributes such as user passwords. We will look at some configuration scenarios below. For full information on available configuration options, please consult the security namespace schema (information from which should be available in your XML editor). 9.4 Configuring an LDAP ServerThe first thing you need to do
is configure the server against which authentication should take place. This is done using the <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
9.4.1 Using an Embedded Test ServerThe <ldap-server root="dc=springframework,dc=org"/> Here
we’ve specified that the root DIT of the directory should be "dc=springframework,dc=org", which is the default. Used this way, the namespace parser will create an embedded Apache Directory server and scan the classpath for any LDIF files, which it will attempt to load into the server. You can customize this behaviour using the <ldap-server ldif="classpath:users.ldif" /> This makes it a lot easier to get up and running with LDAP, since it can be inconvenient to work all the time with an external server. It also insulates the user from the complex bean configuration needed to wire up an Apache Directory server. 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. 9.4.2 Using Bind AuthenticationThis is the most common LDAP authentication scenario. <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/> This simple example would obtain the DN for the user by substituting the user login name in the supplied pattern and attempting to bind as that user with the login password. This is OK if all your users are stored under a single node in the directory. If instead you wished to configure an LDAP search filter to locate the user, you could use the following: <ldap-authentication-provider user-search-filter="(uid={0})" user-search-base="ou=people"/> If used with the server definition above, this would perform a search under the DN 9.4.3 Loading AuthoritiesHow authorities are loaded from groups in the LDAP directory is controlled by the following attributes.
So if we used the following configuration <ldap-authentication-provider user-dn-pattern="uid={0},ou=people" group-search-base="ou=groups" /> and authenticated successfully as user "ben", the subsequent loading of authorities would
perform a search under the directory entry 9.5 Implementation ClassesThe namespace configuration options we’ve used above are simple to use and much more concise than using Spring beans explicitly. There are situations when you may need to know how to configure Spring Security LDAP directly in your application context. You may wish to customize the behaviour of some of the classes, for example. If you’re happy using namespace configuration then you can skip this section and the next one. The main LDAP provider class, 9.5.1 LdapAuthenticator ImplementationsThe 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. There are currently two authentication strategies supplied with Spring Security:
Common FunctionalityBefore 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 BindAuthenticatorThe class PasswordComparisonAuthenticatorThe class 9.5.2 Connecting to the LDAP ServerThe beans discussed above have to be able to connect to the server. They both have to be supplied with a 9.5.3 LDAP Search ObjectsOften a more complicated strategy than simple DN-matching is required to locate a user entry in the directory. This can be encapsulated in an FilterBasedLdapUserSearchThis 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
JDK DirContext class. As explained there, the search filter can be supplied with parameters. For this class, the only valid parameter is 9.5.4 LdapAuthoritiesPopulatorAfter authenticating the user successfully, the 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. 9.5.5 Spring Bean ConfigurationA typical configuration, using some of the beans we’ve discussed here, might look like this: <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/> <property name="userDn" value="cn=manager,dc=springframework,dc=org"/> <property name="password" value="password"/> </bean> <bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"> <constructor-arg> <bean class="org.springframework.security.ldap.authentication.BindAuthenticator"> <constructor-arg ref="contextSource"/> <property name="userDnPatterns"> <list><value>uid={0},ou=people</value></list> </property> </bean> </constructor-arg> <constructor-arg> <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> <constructor-arg ref="contextSource"/> <constructor-arg value="ou=groups"/> <property name="groupRoleAttribute" value="ou"/> </bean> </constructor-arg> </bean> This would set up the provider to access an LDAP server with URL To configure a user search object, which uses the filter <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> <constructor-arg index="0" value=""/> <constructor-arg index="1" value="(uid={0})"/> <constructor-arg index="2" ref="contextSource" /> </bean> and use it by setting the 9.5.6 LDAP Attributes and Customized UserDetailsThe net result of an authentication using public interface UserDetailsContextMapper { UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities); void mapUserToContext(UserDetails user, DirContextAdapter ctx); } Only the first method is relevant for
authentication. If you provide an implementation of this interface and inject it into the The way the
context data is loaded varies slightly depending on the type of authentication you are using. With the 9.6 Active Directory AuthenticationActive Directory supports its own non-standard authentication options, and the normal usage pattern doesn’t fit too cleanly with the standard 9.6.1 ActiveDirectoryLdapAuthenticationProviderConfiguring <bean id="adAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider"> <constructor-arg value="mydomain.com" /> <constructor-arg value="ldap://adserver.mydomain.com/" /> </bean> Note that there is no need to specify a separate By default, the user authorities are obtained from the Active Directory Error CodesBy default, a failed result will cause a standard Spring Security 9.7 LDAP Java ConfigurationYou can find the updates to support LDAP based authentication. The ldap-javaconfig sample provides a complete example of using LDAP based authentication. @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 9.8 AuthenticationProvider9.8.1 AuthenticationProvider Java ConfigurationYou can define custom authentication by exposing a custom
@Bean public SpringAuthenticationProvider springAuthenticationProvider() { return new SpringAuthenticationProvider(); } 9.8.2 AuthenticationProvider XML ConfigurationIn 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 chapter, so we won’t cover it here. If you have a custom implementation of Spring Security’s <authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager> If you want to use a database, then you can use <authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="securityDataSource"/> </authentication-provider> </authentication-manager> Where "securityDataSource" is the name of a <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 <authentication-manager> <authentication-provider ref='myAuthenticationProvider'/> </authentication-manager> where 9.9 UserDetailsServiceYou can define custom authentication by exposing a custom
@Bean public SpringDataUserDetailsService springDataUserDetailsService() { return new SpringDataUserDetailsService(); } You can also customize how passwords are encoded by exposing a @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } 9.10 Password EncodingSpring Security’s
9.10.1 Password HistoryThroughout the years the standard mechanism for storing passwords has evolved. In the beginning passwords were stored in plain text. The passwords were assumed to be safe because the data store the passwords were saved in required credentials to access it. However, malicious users were able to find ways to get large "data dumps" of usernames and passwords using attacks like SQL Injection. As more and more user credentials became public security experts realized we needed to do more to protect users passwords. Developers were then encouraged to store passwords after running them through a one way hash such as SHA-256. When a user tried to authenticate, the hashed password would be compared to the hash of the password that they typed. This meant that the system only needed to store the one way hash of the password. If a breach occurred, then only the one way hashes of the passwords were exposed. Since the hashes were one way and it was computationally difficult to guess the passwords given the hash, it would not be worth the effort to figure out each password in the system. To defeat this new system malicious users decided to create lookup tables known as Rainbow Tables. Rather than doing the work of guessing each password every time, they computed the password once and stored it in a lookup table. To mitigate the effectiveness of Rainbow Tables, developers were encouraged to use salted passwords. Instead of using just the password as input to the hash function, random bytes (known as salt) would be generated for every users' password. The salt and the user’s password would be ran through the hash function which produced a unique hash. The salt would be stored alongside the user’s password in clear text. Then when a user tried to authenticate, the hashed password would be compared to the hash of the stored salt and the password that they typed. The unique salt meant that Rainbow Tables were no longer effective because the hash was different for every salt and password combination. In modern times we realize that cryptographic hashes (like SHA-256) are no longer secure. The reason is that with modern hardware we can perform billions of hash calculations a second. This means that we can crack each password individually with ease. Developers are now encouraged to leverage adaptive one-way functions to store a password. Validation of passwords with adaptive one-way functions are intentionally resource (i.e. CPU, memory, etc) intensive. An adaptive one-way function allows configuring a "work factor" which can grow as hardware gets better. It is recommended that the "work factor" be tuned to take about 1 second to verify a password on your system. This trade off is to make it difficult for attackers to crack the password, but not so costly it puts excessive burden on your own system. Spring Security has attempted to provide a good starting point for the "work factor", but users are encouraged to customize the "work factor" for their own system since the performance will vary drastically from system to system. Examples of adaptive one-way functions that should be used include bcrypt, PBKDF2, scrypt, and Argon2. Because adaptive one-way functions are intentionally resource intensive, validating a username and password for every request will degrade performance of an application significantly. There is nothing Spring Security (or any other library) can do to speed up the validation of the password since security is gained by making the validation resource intensive. Users are encouraged to exchange the long term credentials (i.e. username and password) for a short term credential (i.e. session, OAuth Token, etc). The short term credential can be validated quickly without any loss in security. 9.10.2 DelegatingPasswordEncoderPrior to Spring Security 5.0 the default
Instead Spring Security introduces
You can easily construct an instance of PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); Alternatively, you may create your own custom instance. For example: String idForEncode = "bcrypt"; Map encoders = new HashMap<>(); encoders.put(idForEncode, new BCryptPasswordEncoder()); encoders.put("noop", NoOpPasswordEncoder.getInstance()); encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); encoders.put("scrypt", new SCryptPasswordEncoder()); encoders.put("sha256", new StandardPasswordEncoder()); PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders); Password Storage FormatThe general format for a password is: {id}encodedPassword Such that {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG {noop}password {pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc {scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc= {sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
Password EncodingThe {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG Password MatchingMatching is done based upon the By using the Getting Started ExperienceIf 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. User user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("user") .build(); System.out.println(user.getPassword()); If you are creating multiple users, you can also reuse the builder. UserBuilder users = User.withDefaultPasswordEncoder(); User user = users .username("user") .password("password") .roles("USER") .build(); User admin = users .username("admin") .password("password") .roles("USER","ADMIN") .build(); This does hash the password that is stored, but the passwords are still exposed in memory and in the compiled source code. Therefore, it is still not considered secure for a production environment. For production, you should hash your passwords externally. TroubleshootingThe following error occurs when one of the passwords that are stored has no id as described in the section called “Password Storage Format”. java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233) at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196) The easiest way to resolve the error is to switch to explicitly provide the
@Bean public static NoOpPasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } if you are using XML configuration, you can expose a <b:bean id="passwordEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder" factory-method="getInstance"/> Alternatively, you can prefix all of your passwords with the correct id and continue to use $2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG to {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG For a complete listing of the mappings refer to the Javadoc on PasswordEncoderFactories. 9.10.3 BCryptPasswordEncoderThe BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); 9.10.4 Argon2PasswordEncoderThe Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); 9.10.5 Pbkdf2PasswordEncoderThe Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); 9.10.6 SCryptPasswordEncoderThe SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); 9.10.7 Other PasswordEncodersThere are a significant number of other 9.10.8 Password Encoder XML ConfigurationPasswords 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 <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. 9.11 The Authentication Manager and the NamespaceThe main interface which provides authentication services in Spring Security is the You may want to register additional <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 <security:authentication-manager alias="authenticationManager"> ... </security:authentication-manager> <bean id="customizedFormLoginFilter" class="com.somecompany.security.web.CustomFormLoginFilter"> <property name="authenticationManager" ref="authenticationManager"/> ... </bean>
9.12 Session ManagementHTTP session related functionality is handled by a combination of the 9.12.1 Detecting TimeoutsYou 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 <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: <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
<LocationMatch "/tutorial/logout"> Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT" </LocationMatch> === 9.12.2 Concurrent Session ControlIf 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 <listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener> Then add the following lines to your application context: <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 <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
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 Management chapter. 9.12.3 Session Fixation Attack ProtectionSession 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
When session fixation protection occurs, it results in a 9.12.4 SessionManagementFilterThe If the user is not currently authenticated, the filter will check whether an invalid session ID has been requested (because of a timeout, for example) and will invoke the configured 9.12.5 SessionAuthenticationStrategy
<http> <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" /> <session-management session-authentication-strategy-ref="sas"/> </http> <beans:bean id="myAuthFilter" class= "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> <beans:property name="sessionAuthenticationStrategy" ref="sas" /> ... </beans:bean> <beans:bean id="sas" class= "org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" /> Note that the use of the default, 9.12.6 Concurrency ControlSpring Security is able to prevent a principal from concurrently authenticating to the same application more than a specified number of times. Many ISVs take advantage of this to enforce licensing, whilst network administrators like this feature because it helps prevent people from sharing login names. You can, for example, stop user "Batman" from logging onto the web application from two different sessions. You can either expire their previous login or you can report an error when they try to log in again, preventing the second login. Note that if you are using the second approach, a user who has not explicitly logged out (but who has just closed their browser, for example) will not be able to log in again until their original session expires. Concurrency control is supported by the namespace, so please check the earlier namespace chapter for the simplest configuration. Sometimes you need to customize things though. The implementation uses a specialized version of
To use concurrent session support, you’ll need to add the following to <listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener> In addition, you will need to add the <http> <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" /> <session-management session-authentication-strategy-ref="sas"/> </http> <beans:bean id="redirectSessionInformationExpiredStrategy" class="org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy"> <beans:constructor-arg name="invalidSessionUrl" value="/session-expired.htm" /> </beans:bean> <beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter"> <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" /> <beans:constructor-arg name="sessionInformationExpiredStrategy" ref="redirectSessionInformationExpiredStrategy" /> </beans:bean> <beans:bean id="myAuthFilter" class= "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> <beans:property name="sessionAuthenticationStrategy" ref="sas" /> <beans:property name="authenticationManager" ref="authenticationManager" /> </beans:bean> <beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy"> <beans:constructor-arg> <beans:list> <beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy"> <beans:constructor-arg ref="sessionRegistry"/> <beans:property name="maximumSessions" value="1" /> <beans:property name="exceptionIfMaximumExceeded" value="true" /> </beans:bean> <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"> </beans:bean> <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"> <beans:constructor-arg ref="sessionRegistry"/> </beans:bean> </beans:list> </beans:constructor-arg> </beans:bean> <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" /> Adding
the listener to Querying the SessionRegistry for currently authenticated users and their sessionsSetting up concurrency-control, either through the namespace or using plain beans has the useful side effect of providing you with a reference to the The 9.13 Remember-Me Authentication9.13.1 OverviewRemember-me or persistent-login authentication refers to web sites being able to remember the identity of a principal between sessions. This is typically accomplished by sending a cookie to the browser, with the cookie being detected during future sessions and causing automated login to take place. Spring Security provides the necessary hooks for these operations to take place, and has two concrete remember-me implementations. One uses hashing to preserve the security of cookie-based tokens and the other uses a database or other persistent storage mechanism to store the generated tokens. Note that both implementations require a 9.13.2 Simple Hash-Based Token ApproachThis approach uses hashing to achieve a useful remember-me strategy. In essence a cookie is sent to the browser upon successful interactive authentication, with the cookie being composed as follows: base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) username: As identifiable to the UserDetailsService password: That matches the one in the retrieved UserDetails expirationTime: The date and time when the remember-me token expires, expressed in milliseconds key: A private key to prevent modification of the remember-me token As such the remember-me token is valid only for the period specified, and provided that the username, password and key does not change. Notably, this has a potential security issue in that a captured remember-me token will be usable from any user agent until such time as the token expires. This is the same issue as with digest authentication. If a principal is aware a token has been captured, they can easily change their password and immediately invalidate all remember-me tokens on issue. If more significant security is needed you should use the approach described in the next section. Alternatively remember-me services should simply not be used at all. If you are familiar with the topics discussed in the chapter on namespace configuration, you can enable remember-me authentication just by adding the <http> ... <remember-me key="myAppKey"/> </http> The 9.13.3 Persistent Token ApproachThis approach is based on the article http://jaspan.com/improved_persistent_login_cookie_best_practice with some minor modifications [5]. To use the this approach with namespace configuration, you would supply a datasource reference: <http> ... <remember-me data-source-ref="someDataSource"/> </http> The database should contain a create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null) 9.13.4 Remember-Me Interfaces and ImplementationsRemember-me is used with Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); void loginFail(HttpServletRequest request, HttpServletResponse response); void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); Please refer to the Javadoc for a fuller discussion on what the methods do, although note at this stage that TokenBasedRememberMeServicesThis implementation supports the simpler approach described in
Section 9.13.2, “Simple Hash-Based Token Approach”. The beans required in an application context to enable remember-me services are as follows: <bean id="rememberMeFilter" class= "org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter"> <property name="rememberMeServices" ref="rememberMeServices"/> <property name="authenticationManager" ref="theAuthenticationManager" /> </bean> <bean id="rememberMeServices" class= "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"> <property name="userDetailsService" ref="myUserDetailsService"/> <property name="key" value="springRocks"/> </bean> <bean id="rememberMeAuthenticationProvider" class= "org.springframework.security.authentication.RememberMeAuthenticationProvider"> <property name="key" value="springRocks"/> </bean> Don’t forget to add your
PersistentTokenBasedRememberMeServicesThis class can be used in the same way as
The database schema is described above in Section 9.13.3, “Persistent Token Approach”. 9.14 OpenID SupportThe namespace supports OpenID login either instead of, or in addition to normal form-based login, with a simple change: <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 name="https://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" /> You should be able to login using the 9.14.1 Attribute ExchangeSupport for OpenID 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: <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/. If an attribute must be retrieved for successful
authentication, the OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(); List<OpenIDAttribute> attributes = token.getAttributes(); The 9.15 Anonymous Authentication9.15.1 OverviewIt’s generally considered good security practice to adopt a "deny-by-default" where you explicitly specify what is allowed and disallow everything else. Defining what is accessible to unauthenticated users is a similar situation, particularly for web applications. Many sites require
that users must be authenticated for anything other than a few URLs (for example the home and login pages). In this case it is easiest to define access configuration attributes for these specific URLs rather than have for every secured resource. Put differently, sometimes it is nice to say This is what we mean by anonymous authentication. Note that there is no real conceptual difference between a user who is "anonymously authenticated" and an unauthenticated user. Spring Security’s anonymous authentication just gives you a more convenient way to configure your access-control attributes. Calls to servlet API calls such as
There are other situations where anonymous authentication is useful, such as when an auditing interceptor queries the 9.15.2 ConfigurationAnonymous authentication support is provided automatically when using the HTTP configuration Spring Security 3.0 and can be customized (or disabled) using the Three classes that together provide the anonymous authentication feature. <bean id="anonymousAuthFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter"> <property name="key" value="foobar"/> <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/> </bean> <bean id="anonymousAuthenticationProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider"> <property name="key" value="foobar"/> </bean> The As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security applied to them. For example: <bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/> <property name="securityMetadata"> <security:filter-security-metadata-source> <security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/**' access='ROLE_USER'/> </security:filter-security-metadata-source>" + </property> </bean> 9.15.3 AuthenticationTrustResolverRounding out the
anonymous authentication discussion is the You will often see the 9.16 Pre-Authentication ScenariosThere are situations where you want to use Spring Security for authorization, but the user has already been reliably authenticated by some external system prior to accessing the application. We refer to these situations as "pre-authenticated" scenarios. Examples include X.509, Siteminder and authentication by the Java EE container in which the application is running. When using pre-authentication, Spring Security has to
The details will depend on the external authentication mechanism. A user might be identified by their
certificate information in the case of X.509, or by an HTTP request header in the case of Siteminder. If relying on container authentication, the user will be identified by calling the 9.16.1 Pre-Authentication Framework ClassesBecause most pre-authentication mechanisms follow the same pattern, Spring Security has a set of classes which provide an internal framework for implementing pre-authenticated authentication providers. This removes
duplication and allows new implementations to be added in a structured fashion, without having to write everything from scratch. You don’t need to know about these classes if you want to use something like X.509 authentication, as it already has a namespace configuration option which is simpler to use and get started with. If
you need to use explicit bean configuration or are planning on writing your own implementation then an understanding of how the provided implementations work will be useful. You will find classes under the AbstractPreAuthenticatedProcessingFilterThis class will check the current contents of the security context and, if empty, it will attempt to extract user information from the HTTP request and submit it to the protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); After calling these, the filter will create a Like other Spring Security authentication filters, the pre-authentication filter has an J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceIf the filter is configured with an There is an additional stage where the roles (or attributes) are mapped to Spring Security PreAuthenticatedAuthenticationProviderThe pre-authenticated provider has little more to do than load the public interface AuthenticationUserDetailsService { UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; } This interface may have also other uses but with pre-authentication it allows access to the authorities which were packaged in the Http403ForbiddenEntryPointThe 9.16.2 Concrete ImplementationsX.509 authentication is covered in its own chapter. Here we’ll look at some classes which provide support for other pre-authenticated scenarios. Request-Header Authentication (Siteminder)An external authentication system may supply information to the application by setting specific headers on the HTTP request. A well-known example of this is Siteminder, which passes the username in a header called
Siteminder Example ConfigurationA typical configuration using this filter would look like this: <security:http> <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" /> </security:http> <bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter"> <property name="principalRequestHeader" value="SM_USER"/> <property name="authenticationManager" ref="authenticationManager" /> </bean> <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> <property name="preAuthenticatedUserDetailsService"> <bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> <property name="userDetailsService" ref="userDetailsService"/> </bean> </property> </bean> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="preauthAuthProvider" /> </security:authentication-manager> We’ve assumed here that the
security namespace is being used for configuration. It’s also assumed that you have added a Java EE Container AuthenticationThe class There is a sample application in the codebase which uses this approach, so get hold of the code from github and have a look at the application context file if you are interested. The code is in the
9.17 Java Authentication and Authorization Service (JAAS) Provider9.17.1 OverviewSpring Security provides a package able to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is discussed in detail below. 9.17.2 AbstractJaasAuthenticationProviderThe JAAS CallbackHandlerMost JAAS In a Spring Security deployment, Spring Security is responsible for this user interaction (via
the authentication mechanism). Thus, by the time the authentication request is delegated through to JAAS, Spring Security’s authentication mechanism will already have fully-populated an Therefore, the JAAS package for Spring Security provides two default callback handlers, For those needing full control over the callback behavior, internally
JAAS AuthorityGranterJAAS works with principals. Even "roles" are represented as principals in JAAS. Spring Security, on the other hand, works with An Spring Security does not include any production
9.17.3 DefaultJaasAuthenticationProviderThe InMemoryConfigurationIn order to make it easy to inject a DefaultJaasAuthenticationProvider Example ConfigurationWhile the Spring configuration for An
example configuration of <bean id="jaasAuthProvider" class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider"> <property name="configuration"> <bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration"> <constructor-arg> <map> <entry key="SPRINGSECURITY"> <array> <bean class="javax.security.auth.login.AppConfigurationEntry"> <constructor-arg value="sample.SampleLoginModule" /> <constructor-arg> <util:constant static-field= "javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/> </constructor-arg> <constructor-arg> <map></map> </constructor-arg> </bean> </array> </entry> </map> </constructor-arg> </bean> </property> <property name="authorityGranters"> <list> <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/> </list> </property> </bean> 9.17.4 JaasAuthenticationProviderThe Let’s assume we have a JAAS login configuration file, JAASTest { sample.SampleLoginModule required; }; Like all Spring Security beans, the <bean id="jaasAuthenticationProvider" class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider"> <property name="loginConfig" value="/WEB-INF/login.conf"/> <property name="loginContextName" value="JAASTest"/> <property name="callbackHandlers"> <list> <bean class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/> <bean class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/> </list> </property> <property name="authorityGranters"> <list> <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/> </list> </property> </bean> 9.17.5 Running as a SubjectIf configured, the Subject subject = Subject.getSubject(AccessController.getContext()); This integration can easily be configured using the jaas-api-provision attribute. This feature is useful when integrating with legacy or external API’s that rely on the JAAS Subject being populated. 9.18 CAS Authentication9.18.1 OverviewJA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other initiatives, JA-SIG’s Central Authentication Service is open source, widely used, simple to understand, platform independent, and supports proxy capabilities. Spring Security fully supports CAS, and provides an easy migration path from single-application deployments of Spring Security through to multiple-application deployments secured by an enterprise-wide CAS server. You can learn more about CAS at https://www.apereo.org. You will also need to visit this site to download the CAS Server files. 9.18.2 How CAS WorksWhilst the CAS web site contains documents that detail the architecture of CAS, we present the general overview again here within the context of Spring Security. Spring Security 3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4. Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply a standard WAR file, so there isn’t anything difficult about setting up your server. Inside the WAR file you will customise the login and other single sign on pages displayed to users. When deploying a CAS 3.4 server, you will also need to specify an Apart from the CAS server itself, the other key players are of course the secure web applications deployed throughout your enterprise. These web applications are known as "services". There are three types of services. Those that authenticate service tickets, those that can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket differs because the list of proxies must be validated and often times a proxy ticket can be reused. Spring Security and CAS Interaction SequenceThe basic interaction between a web browser, CAS server and a Spring Security-secured service is as follows:
It’s good that you’re still here! Let’s now look at how this is configured 9.18.3 Configuration of CAS ClientThe web application side of CAS is made easy due to Spring Security. It is assumed you already know the basics of using Spring Security, so these are not covered again below. We’ll assume a namespace based configuration is being used and add in the CAS beans as required. Each section builds upon the previous section. A fullCAS sample application can be found in the Spring Security Samples. Service Ticket AuthenticationThis section describes how to setup Spring Security to authenticate Service Tickets. Often times this is all a web application requires. You will need to add a <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"> <property name="service" value="https://localhost:8443/cas-sample/login/cas"/> <property name="sendRenew" value="false"/> </bean> The The following beans should be configured to commence the CAS authentication process (assuming you’re using a namespace configuration): <security:http entry-point-ref="casEntryPoint"> ... <security:custom-filter position="CAS_FILTER" ref="casFilter" /> </security:http> <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> <property name="authenticationManager" ref="authenticationManager"/> </bean> <bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"> <property name="loginUrl" value="https://localhost:9443/cas/login"/> <property name="serviceProperties" ref="serviceProperties"/> </bean> For
CAS to operate, the The Next you need to add a <security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="casAuthenticationProvider" /> </security:authentication-manager> <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> <property name="authenticationUserDetailsService"> <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> <constructor-arg ref="userService" /> </bean> </property> <property name="serviceProperties" ref="serviceProperties" /> <property name="ticketValidator"> <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> <constructor-arg index="0" value="https://localhost:9443/cas" /> </bean> </property> <property name="key" value="an_id_for_this_auth_provider_only"/> </bean> <security:user-service id="userService"> <security:user name="joe" password="{noop}joe" authorities="ROLE_USER" /> ... </security:user-service> The The beans are all reasonably self-explanatory if you refer back to the How CAS Works section. This completes the most basic configuration for CAS. If you haven’t made any mistakes, your web application should happily work within the framework of CAS single sign on. No other parts of Spring Security need to be concerned about the fact CAS handled authentication. In the following sections we will discuss some (optional) more advanced configurations. Single LogoutThe CAS protocol supports Single Logout and can be easily added to your Spring Security configuration. Below are updates to the Spring Security configuration that handle Single Logout <security:http entry-point-ref="casEntryPoint"> ... <security:logout logout-success-url="/cas-logout.jsp"/> <security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/> <security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/> </security:http> <bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/> <bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> <constructor-arg value="https://localhost:9443/cas/logout"/> <constructor-arg> <bean class= "org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/> </constructor-arg> <property name="filterProcessesUrl" value="/logout/cas"/> </bean> The It might be confusing why both the
The next step is to add the following to your web.xml <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class> org.jasig.cas.client.session.SingleSignOutHttpSessionListener </listener-class> </listener> When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is recommended to add the Authenticating to a Stateless Service with CASThis section describes how to authenticate to a service using CAS. In other words, this section discusses how to setup a client that uses a service that authenticates with CAS. The next section describes how to setup a stateless service to Authenticate using CAS. Configuring CAS to Obtain Proxy Granting TicketsIn order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket (PGT). This section describes how to configure Spring Security to obtain a PGT building upon thencas-st[Service Ticket Authentication] configuration. The first step is to include a <bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/> The
next step is to update the <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> ... <property name="ticketValidator"> <bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"> <constructor-arg value="https://localhost:9443/cas"/> <property name="proxyCallbackUrl" value="https://localhost:8443/cas-sample/login/cas/proxyreceptor"/> <property name="proxyGrantingTicketStorage" ref="pgtStorage"/> </bean> </property> </bean> The last step is to update the <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> ... <property name="proxyGrantingTicketStorage" ref="pgtStorage"/> <property name="proxyReceptorUrl" value="/login/cas/proxyreceptor"/> </bean> Calling a Stateless Service Using a Proxy TicketNow that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to
authenticate to a stateless service. The CAS sample application contains a working example in the protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal(); final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl); final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8"); String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8"); ... } Proxy Ticket AuthenticationThe Because remoting protocols have no way of presenting themselves within the context of an One obvious option is to not use CAS at all for remoting protocol clients. However, this would eliminate many of the desirable features of CAS. As a middle-ground, the This section builds upon the previous sections to accommodate proxy ticket authentication. The first step is to specify to authenticate all artifacts as shown below. <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"> ... <property name="authenticateAllArtifacts" value="true"/> </bean> The next step is to specify <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> ... <property name="serviceProperties" ref="serviceProperties"/> <property name="authenticationDetailsSource"> <bean class= "org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"> <constructor-arg ref="serviceProperties"/> </bean> </property> </bean> You will also need to update the <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> ... <property name="ticketValidator"> <bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"> <constructor-arg value="https://localhost:9443/cas"/> <property name="acceptAnyProxy" value="true"/> </bean> </property> <property name="statelessTicketCache"> <bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache"> <property name="cache"> <bean class="net.sf.ehcache.Cache" init-method="initialise" destroy-method="dispose"> <constructor-arg value="casTickets"/> <constructor-arg value="50"/> <constructor-arg value="true"/> <constructor-arg value="false"/> <constructor-arg value="3600"/> <constructor-arg value="900"/> </bean> </property> </bean> </property> </bean> 9.19 X.509 Authentication9.19.1 OverviewThe most common use of X.509 certificate authentication is in verifying the identity of a server when using SSL, most commonly when using HTTPS from a browser. The browser will automatically check that the certificate presented by a server has been issued (ie digitally signed) by one of a list of trusted certificate authorities which it maintains. You can also use SSL with "mutual authentication"; the server will then request a valid certificate from the client as part of the SSL handshake. The server will authenticate the client by checking that its certificate is signed by an acceptable authority. If a valid certificate has been provided, it can be obtained through the servlet API in an application. Spring Security X.509 module extracts the certificate using a filter. It maps the certificate to an application user and loads that user’s set of granted authorities for use with the standard Spring Security infrastructure. You should be familiar with using certificates and setting up client authentication for your servlet container before attempting to use it with Spring Security. Most of the work is in creating and installing suitable certificates and keys. For example, if you’re using Tomcat then read the instructions here https://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html. It’s important that you get this working before trying it out with Spring Security 9.19.2 Adding X.509 Authentication to Your Web ApplicationEnabling X.509 client authentication is very straightforward. Just add the <http> ... <x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/>; </http> The element has two optional attributes:
The 9.19.3 Setting up SSL in TomcatThere are some pre-generated certificates in the To run tomcat with SSL support, drop the <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" keystoreFile="${catalina.home}/conf/server.jks" keystoreType="JKS" keystorePass="password" truststoreFile="${catalina.home}/conf/server.jks" truststoreType="JKS" truststorePass="password" />
9.20 Run-As Authentication Replacement9.20.1 OverviewThe By temporarily replacing the 9.20.2 ConfigurationA Authentication buildRunAs(Authentication authentication, Object object, List<ConfigAttribute> config); boolean supports(ConfigAttribute attribute); boolean supports(Class clazz); The first method returns the One concrete implementation of
a The replacement To ensure malicious code does not create a <bean id="runAsManager" class="org.springframework.security.access.intercept.RunAsManagerImpl"> <property name="key" value="my_run_as_password"/> </bean> <bean id="runAsAuthenticationProvider" class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider"> <property name="key" value="my_run_as_password"/> </bean> By using the same key, each 9.21 Form Login9.21.1 Form Login Java ConfigurationYou 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 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { } And then override the protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests .anyRequest().authenticated() ) .formLogin(formLogin -> formLogin .loginPage("/login") .permitAll() ); }
An example log in page implemented with JSPs for our current configuration can be seen below:
<c:url value="/login" var="loginUrl"/> <form action="${loginUrl}" method="post"> <c:if test="${param.error != null}"> <p> Invalid username and password. </p> </c:if> <c:if test="${param.logout != null}"> <p> You have been logged out. </p> </c:if> <p> <label for="username">Username</label> <input type="text" id="username" name="username"/> </p> <p> <label for="password">Password</label> <input type="password" id="password" name="password"/> </p> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <button type="submit" class="btn">Log in</button> </form>
9.21.2 Form Login XML ConfigurationForm and Basic Login OptionsYou 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: <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 <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 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 If you want to use basic authentication instead of form login, then change the configuration to <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. 9.22 Basic and Digest AuthenticationBasic 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. 9.22.1 BasicAuthenticationFilter
9.22.2 ConfigurationTo implement HTTP Basic Authentication, you need to add a <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 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 9.23 DigestAuthenticationFilter
Central to Digest Authentication is a "nonce". This is a value the server generates. Spring Security’s nonce adopts the following format: base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) expirationTime: The date and time when the nonce expires, expressed in milliseconds key: A private key to prevent modification of the nonce token The An appropriate value for the Because of the more complex implementation of Digest Authentication, there are often user agent issues. For example, Internet Explorer fails to present an “opaque” token on subsequent requests in the same session. Spring Security filters therefore encapsulate all state information into the “nonce” token instead. In our testing, Spring Security’s implementation works reliably with Mozilla Firefox and Internet Explorer, correctly handling nonce timeouts etc. 9.23.1 ConfigurationNow that we’ve reviewed the theory, let’s see how to use it. To implement HTTP Digest Authentication, it is necessary to define <bean id="digestFilter" class= "org.springframework.security.web.authentication.www.DigestAuthenticationFilter"> <property name="userDetailsService" ref="jdbcDaoImpl"/> <property name="authenticationEntryPoint" ref="digestEntryPoint"/> <property name="userCache" ref="userCache"/> </bean> <bean id="digestEntryPoint" class= "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint"> <property name="realmName" value="Contacts Realm via Digest Authentication"/> <property name="key" value="acegi"/> <property name="nonceValiditySeconds" value="10"/> </bean> The configured Like Digest Authentication’s RFC offers a range of additional features to further increase security. For example, the nonce can be changed on every request. Despite this, Spring Security implementation was designed to minimise the complexity of the implementation (and the doubtless user agent incompatibilities that would emerge), and avoid needing to store server-side state. You are invited to review RFC 2617 if you wish to explore these features in more detail. As far as we are aware, Spring Security’s implementation does comply with the minimum standards of this RFC. 9.24 Handling Logouts9.24.1 Logout Java ConfigurationWhen using the
Similar to configuring login capabilities, however, you also have various options to further customize your logout requirements: protected void configure(HttpSecurity http) throws Exception { http .logout(logout -> logout .logoutUrl("/my/logout") .logoutSuccessUrl("/my/index") .logoutSuccessHandler(logoutSuccessHandler) .invalidateHttpSession(true) .addLogoutHandler(logoutHandler) .deleteCookies(cookieNamesToClear) ) ... }
Generally, in order to customize logout functionality, you can add 9.24.2 Logout XML ConfigurationThe 9.24.4 LogoutSuccessHandlerThe The following implementations are provided:
As mentioned above, you don’t need to specify the The 9.25 Setting a Custom AuthenticationEntryPointIf 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
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 technical overview chapter. What are the two components of an asymmetric encryption system necessary for encryption and decryption operations?Asymmetric encryption uses a mathematically related pair of keys for encryption and decryption: a public key and a private key. If the public key is used for encryption, then the related private key is used for decryption. If the private key is used for encryption, then the related public key is used for decryption.
How is a message integrity check MIC different from a message authentication code MAC )? Quizlet?How is a Message Integrity Check (MIC) different from a Message Authentication Code (MAC)? a MIC only hashes the message, while a MAC incorporates a secret key; A MIC can be thought of as just a checksum or hash digest of a message, while a MAC uses a shared secret to generate the checksum.
Which type of encryption does SSL TLS use quizlet?SSL/TLS uses both symmetric and asymmetric cryptography.
What are components that make up a cryptosystem?Components of a Cryptosystem. Plaintext. It is the data to be protected during transmission.. Encryption Algorithm. ... . Ciphertext. ... . Decryption Algorithm, It is a mathematical process, that produces a unique plaintext for any given ciphertext and decryption key. ... . Encryption Key. ... . Decryption Key.. |