Spring Security supports both HTTP and HTTPS. In our application, we can specify particular URL pattern which can only be accessed over HTTPS. That means even if a user attempts to access those URLs using HTTP, it will be redirected to the HTTPS.
Example
Java Config class
@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan
public class AppConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/**").hasRole("USER")
.antMatchers("/quests/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
//following enables https for the specified URL pattern
.requiresChannel().antMatchers("/users/**").requiresSecure();
}
@Override
public void configure(AuthenticationManagerBuilder builder)
throws Exception {
builder.inMemoryAuthentication()
.withUser("joe")
.password(passwordEncoder().encode("123"))
.roles("USER");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/views/");
vr.setSuffix(".jsp");
return vr;
}
}
Controller
@Controller
public class MyController {
@RequestMapping(value = {"/users/**","/quests/**"})
public String handleRequest(HttpServletRequest request, Model model) {
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
model.addAttribute("uri", request.getRequestURI())
.addAttribute("user", auth.getName())
.addAttribute("roles", auth.getAuthorities());
return "my-page";
}
}
View
src/main/webapp/WEB-INF/views/my-page.jsp<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<body>
<p>URI: ${uri} <br/>
User : ${user} <br/>
roles: ${roles} <br/><br/>
<a href="http://localhost:8080/users/">/users/</a><br/>
<a href="http://localhost:8080/quests/">/quests/</a><br/><br/>
</p>
<form action="/logout" method="post">
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
<input type="submit" value="Logout">
</form>
</body>
</html>
As seen above, both links' href attributes are specified with 'http'. Clicking on /users/, however, will be redirected to 'https' per our Java config.
Configuring tomcat7-maven-plugin to use HTTPS
For testing purpose or even in dev environment, we can configure tomcat7-maven-plugin to access HTTPS URLs:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<httpsPort>8443</httpsPort>
<keystoreFile>C:\my-cert-dir\localhost-rsa.jks</keystoreFile>
<keystorePass>123456</keystorePass>
</configuration>
</plugin>
The keystore file should be created by keytool at the location specified above by <keystoreFile/>. Checkout this tutorial for details.
Running the example application
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run-war
Output
Entering 'localhost:8080/quests/' in the address bar:
Clicking on '/users/' will be redirected to 'https' and as we have configured this URL to be accessed only by 'USER' role, login form will be shown at first access:
Note that Chrome shows 'Not secure' warning for self-signed certificate. For a real production application, we should get the certificate from a certificate authority.
Entering valid user/password and clicking on 'Login' button:
Clicking on /quests/:
'/quests/' can also be accessed via https. Entering 'https://localhost:8443/quests/' in the address bar:
Example ProjectDependencies and Technologies Used: - spring-security-web 5.0.0.RELEASE: spring-security-web.
- spring-security-config 5.0.0.RELEASE: spring-security-config.
- spring-webmvc 5.0.0.RELEASE: Spring Web MVC.
- javax.servlet-api 3.1.0 Java Servlet API
- jstl 1.2 javax.servlet:jstl
- JDK 1.8
- Maven 3.3.9
|