123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- = Hello Spring MVC Security Java Config
- :author: Rob Winch
- :starter-appname: insecuremvc
- :completed-appname: hellomvc-jc
- :include-dir: _includes
- :hello-include-dir: _hello-includes
- This guide provides instructions on how to add Spring Security to an existing Spring MVC application without the use of XML.
- include::{include-dir}/setting-up-the-sample.asc[]
- Verify the application is working:
- * A page displaying a user's inbox can be seen at http://localhost:8080/sample/
- * Try clicking on the Compose link and creating a message. The message details should be displayed.
- * Now click on the Inbox link and see the message listed. You can click on the summary link to see the details displayed again.
- include::{hello-include-dir}/secure-the-application.asc[]
- === Registering Spring Security with the war
- We have created the Spring Security configuration, but we still need to register it with the war. This can be done using the following steps:
- * Right click the _spring-security-samples-{starter-appname}_ project the Package Explorer view
- * Select *New->Class*
- * Enter _org.springframework.security.samples.config_ for the *Package*
- * Enter MessageSecurityWebApplicationInitializer for the *Name*
- * Click *Finish*
- * Replace the file with the following contents:
- .src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java
- [source,java]
- ----
- package org.springframework.security.samples.config;
- import org.springframework.security.web.context.*;
- public class MessageSecurityWebApplicationInitializer
- extends AbstractSecurityWebApplicationInitializer {
- }
- ----
- The `MessageSecurityWebApplicationInitializer` will automatically register the springSecurityFilterChain Filter for every URL in your application. If Filters are added within other `WebApplicationInitializer` instances we can use `@Order` to control the ordering of the Filter instances.
- === Verify SecurityConfig is loaded
- Just because <<security-config-java,SecurityConfig>> exists, does not mean that our Spring application knows about it. In this instance, our Spring root application context is initialized using MessageWebApplicationInitializer which is included with our spring-security-samples-messages-jc project. You can find a snippet of it below:
- [[message-web-application-inititializer-java]]
- .MessageWebApplicationInitializer.java
- [source,java]
- ----
- public class MessageWebApplicationInitializer extends
- AbstractAnnotationConfigDispatcherServletInitializer {
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return new Class[] { RootConfiguration.class };
- }
- // ... other overrides ...
- }
- ----
- You will notice it is loading the `RootConfiguration` class which is also included in our spring-security-samples-messages-jc project.
- [[root-configuration-java]]
- .RootConfiguration.java
- [source,java]
- ----
- @Configuration
- @ComponentScan
- public class RootConfiguration {
- }
- ----
- The `@ComponentScan` is loading all configuration within the same package (and child packags) as `RootConfiguration`. Since <<security-config-java,SecurityConfig>> is in this package, it will be loaded with our existing setup and there is nothing more to do.
- NOTE: Had <<security-config-java,SecurityConfig>> not been loaded, we could have used an `@Import(SecurityConfig)` above the class definition of <<root-configuration-java,RootConfiguration>> or added <<security-config-java,SecurityConfig>> as one of the results for `getRootConfigClasses()`.
- include::{hello-include-dir}/exploring-the-secured-application.asc[]
- ==== Displaying the user name
- Now that we have authenticated, let's see how our application is displaying the username if the user is authenticated.
- .messages-jc/src/main/resources/views/layout.html
- [source,html]
- ----
- <div th:if="${#httpServletRequest.remoteUser != null}">
- <p th:text="${#httpServletRequest.remoteUser}">
- sample_user
- </p>
- </div>
- ----
- In our samples we use http://www.thymeleaf.org/[Thymeleaf], but any view technology will work. Any technology can inspect the `HttpServletRequest#getRemoteUser()` to view the current user since Spring Security integrates with the <<servlet-api-integration,Servlet API methods>>.
- WARNING: The Thymeleaf ensures the username is escaped to avoid http://en.wikipedia.org/wiki/Cross-site_scripting[XSS vulnerabilities] Regardless of how an application renders user inputed values, it should ensure that the values are properly escaped.
- ==== Logging out
- We can view the user name, but how are we able to log out? Below you can see how we are able to log out.
- .messages-jc/src/main/resources/views/layout.html
- [source,html]
- ----
- <form th:action="@{/logout}" method="post">
- <input type="submit" value="Log out" />
- </form>
- ----
- If you try to log out right now the request will fail. The reason is that Spring Security is protecting against CSRF attakcks and there is no CSRF token include in our request. Update our configuration to use the `@EnableWebMvcSecurity` annotation which will do the same as `@EnableWebMvcSecurity` and provide integration with Spring MVC. Among other things, it will ensure our CSRF Token is included in our forms automatically when using Thymleaf 2.1+ or Spring MVC taglibs.
- .src/main/java/org/springframework/security/samples/config/SecurityConfig.java
- [source,java]
- ----
- import org.springframework.security.config.annotation.web.servlet.configuration.*;
- @Configuration
- @EnableWebMvcSecurity
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- ----
- In order to help protect against http://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attacks], by default, Spring Security Java Configuration log out requires:
- * the HTTP method must be a POST
- * the CSRF token must be added to the request. Since we have used `@EnableWebMvcSecurity` and are using Thymeleaf, the CSRF token is automatically added as a hidden input for you (view the source to see it).
- NOTE: If you were not using Spring MVC taglibs or Thymeleaf, you can access the CsrfToken on the ServletRequest using the attribute _csrf. You can find an example of including the CSRF token in a JSP within the link:helloworld.html[Hello Spring Security Java Config].
- Restart the application server and click the Log out button and see that the application logs you out successfully.
- == Conclusion
- You should now know how to secure your application using Spring Security without using any XML. Next, we will see how to link:form.html[customize our login form].
|