JAVA-67:renamed spring-security-mvc-custom to
spring-security-web-mvc-custom
This commit is contained in:
13
spring-security-modules/spring-security-web-mvc-custom/.gitignore
vendored
Normal file
13
spring-security-modules/spring-security-web-mvc-custom/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
*.class
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
@@ -0,0 +1,23 @@
|
||||
## Spring Security MVC Custom
|
||||
|
||||
This module contains articles about Spring Security with custom MVC applications
|
||||
|
||||
### The Course
|
||||
|
||||
The "REST With Spring" Classes: http://github.learnspringsecurity.com
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Spring Security Remember Me](https://www.baeldung.com/spring-security-remember-me)
|
||||
- [Redirect to different pages after Login with Spring Security](https://www.baeldung.com/spring_redirect_after_login)
|
||||
- [Changing Spring Model Parameters with Handler Interceptor](https://www.baeldung.com/spring-model-parameters-with-handler-interceptor)
|
||||
- [Introduction to Spring MVC HandlerInterceptor](https://www.baeldung.com/spring-mvc-handlerinterceptor)
|
||||
- [Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions](https://www.baeldung.com/spring-mvc-custom-handler-interceptor)
|
||||
- [A Guide to CSRF Protection in Spring Security](https://www.baeldung.com/spring-security-csrf)
|
||||
- [How to Manually Authenticate User with Spring Security](https://www.baeldung.com/manually-set-user-authentication-spring-security)
|
||||
|
||||
### Build the Project
|
||||
|
||||
```
|
||||
mvn clean install
|
||||
```
|
||||
203
spring-security-modules/spring-security-web-mvc-custom/pom.xml
Normal file
203
spring-security-modules/spring-security-web-mvc-custom/pom.xml
Normal file
@@ -0,0 +1,203 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-web-mvc-custom</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>spring-security-web-mvc-custom</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-spring-5</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring Security -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${spring-security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${spring-security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${spring-security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- ops -->
|
||||
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>com.codahale.metrics</groupId> -->
|
||||
<!-- <artifactId>metrics-core</artifactId> -->
|
||||
<!-- <version>3.0.1</version> -->
|
||||
<!-- </dependency> -->
|
||||
|
||||
<!-- util -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<version>${spring-security.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-security-mvc-custom</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>jetty8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8082</cargo.servlet.port>
|
||||
</properties>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>19.0</guava.version>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.baeldung.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
public MySimpleUrlAuthenticationSuccessHandler() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException {
|
||||
handle(request, response, authentication);
|
||||
clearAuthenticationAttributes(request);
|
||||
}
|
||||
|
||||
// IMPL
|
||||
|
||||
protected void handle(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException {
|
||||
final String targetUrl = determineTargetUrl(authentication);
|
||||
|
||||
if (response.isCommitted()) {
|
||||
logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
redirectStrategy.sendRedirect(request, response, targetUrl);
|
||||
}
|
||||
|
||||
protected String determineTargetUrl(final Authentication authentication) {
|
||||
|
||||
Map<String, String> roleTargetUrlMap = new HashMap<>();
|
||||
roleTargetUrlMap.put("ROLE_USER", "/homepage.html");
|
||||
roleTargetUrlMap.put("ROLE_ADMIN", "/console.html");
|
||||
|
||||
final Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
||||
for (final GrantedAuthority grantedAuthority : authorities) {
|
||||
|
||||
String authorityName = grantedAuthority.getAuthority();
|
||||
if(roleTargetUrlMap.containsKey(authorityName)) {
|
||||
return roleTargetUrlMap.get(authorityName);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary authentication-related data which may have been stored in the session
|
||||
* during the authentication process.
|
||||
*/
|
||||
protected final void clearAuthenticationAttributes(final HttpServletRequest request) {
|
||||
final HttpSession session = request.getSession(false);
|
||||
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.spring;
|
||||
|
||||
import com.baeldung.web.interceptor.LoggerInterceptor;
|
||||
import com.baeldung.web.interceptor.SessionTimerInterceptor;
|
||||
import com.baeldung.web.interceptor.UserInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.JstlView;
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@ComponentScan("com.baeldung.web.controller")
|
||||
public class MvcConfig implements WebMvcConfigurer {
|
||||
|
||||
public MvcConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
registry.addViewController("/anonymous.html");
|
||||
|
||||
registry.addViewController("/login.html");
|
||||
registry.addViewController("/homepage.html");
|
||||
registry.addViewController("/console.html");
|
||||
registry.addViewController("/csrfHome.html");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver viewResolver() {
|
||||
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
|
||||
|
||||
bean.setViewClass(JstlView.class);
|
||||
bean.setPrefix("/WEB-INF/view/");
|
||||
bean.setSuffix(".jsp");
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(final InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new LoggerInterceptor());
|
||||
registry.addInterceptor(new UserInterceptor());
|
||||
registry.addInterceptor(new SessionTimerInterceptor());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.spring;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class MyUserDetailsService implements UserDetailsService {
|
||||
|
||||
private Map<String, User> roles = new HashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
roles.put("admin", new User("admin", "{noop}admin1", getAuthority("ROLE_ADMIN")));
|
||||
roles.put("user", new User("user", "{noop}user1", getAuthority("ROLE_USER")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) {
|
||||
return roles.get(username);
|
||||
}
|
||||
|
||||
private List<GrantedAuthority> getAuthority(String role) {
|
||||
return Collections.singletonList(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.baeldung.spring;
|
||||
|
||||
import com.baeldung.security.MySimpleUrlAuthenticationSuccessHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
@Configuration
|
||||
//@ImportResource({ "classpath:webSecurityConfig.xml" })
|
||||
@EnableWebSecurity
|
||||
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public SecSecurityConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Bean("authenticationManager")
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/anonymous*").anonymous()
|
||||
.antMatchers("/login*").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/login.html")
|
||||
.loginProcessingUrl("/login")
|
||||
.successHandler(myAuthenticationSuccessHandler())
|
||||
.failureUrl("/login.html?error=true")
|
||||
|
||||
.and()
|
||||
.logout().deleteCookies("JSESSIONID")
|
||||
|
||||
.and()
|
||||
.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(86400)
|
||||
|
||||
.and()
|
||||
.csrf().disable()
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){
|
||||
return new MySimpleUrlAuthenticationSuccessHandler();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.web.controller;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
// to test csrf
|
||||
@Controller
|
||||
public class BankController {
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@RequestMapping(value = "/transfer", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public int transfer(@RequestParam("accountNo") final int accountNo, @RequestParam("amount") final int amount) {
|
||||
logger.info("Transfer to {}", accountNo);
|
||||
return amount;
|
||||
}
|
||||
|
||||
// write - just for test
|
||||
@RequestMapping(value = "/transfer", method = RequestMethod.POST)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public void create(@RequestParam("accountNo") final int accountNo, @RequestParam("amount") final int amount) {
|
||||
logger.info("Transfer to {}", accountNo);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.baeldung.web.controller;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.baeldung.web.dto.Foo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(value = "/auth/foos")
|
||||
public class FooController {
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public FooController() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// read - single
|
||||
|
||||
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Foo findById(@PathVariable("id") final Long id, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
|
||||
return new Foo(randomAlphabetic(6));
|
||||
}
|
||||
|
||||
// read - multiple
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public List<Foo> findAll() {
|
||||
return Arrays.asList(new Foo(randomAlphabetic(6)));
|
||||
}
|
||||
|
||||
// write - just for test
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ResponseBody
|
||||
public Foo create(@RequestBody final Foo foo) {
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.web.controller;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(value = "/custom")
|
||||
public class LoginController {
|
||||
|
||||
@Resource(name="authenticationManager")
|
||||
private AuthenticationManager authManager;
|
||||
|
||||
public LoginController() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// custom login
|
||||
|
||||
@RequestMapping(value = "/login", method = RequestMethod.POST)
|
||||
public void login(@RequestParam("username") final String username, @RequestParam("password") final String password, final HttpServletRequest request) {
|
||||
UsernamePasswordAuthenticationToken authReq =
|
||||
new UsernamePasswordAuthenticationToken(username, password);
|
||||
Authentication auth = authManager.authenticate(authReq);
|
||||
SecurityContext sc = SecurityContextHolder.getContext();
|
||||
sc.setAuthentication(auth);
|
||||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute("SPRING_SECURITY_CONTEXT", sc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.web.controller;
|
||||
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(value = "/custom")
|
||||
public class PrintUserController {
|
||||
|
||||
public PrintUserController() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// print user
|
||||
|
||||
@RequestMapping(value = "/print", method = RequestMethod.GET)
|
||||
public void printUser() {
|
||||
SecurityContext sc = SecurityContextHolder.getContext();
|
||||
System.out.println("Logged User: "+sc.getAuthentication().getName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.web.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Foo implements Serializable {
|
||||
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Foo() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Foo(final String name) {
|
||||
super();
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Foo other = (Foo) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Foo [name=")
|
||||
.append(name)
|
||||
.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class LoggerInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(LoggerInterceptor.class);
|
||||
|
||||
/**
|
||||
* Executed before actual handler is executed
|
||||
**/
|
||||
@Override
|
||||
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
|
||||
log.info("[preHandle][" + request + "]" + "[" + request.getMethod() + "]" + request.getRequestURI() + getParameters(request));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed before after handler is executed
|
||||
**/
|
||||
@Override
|
||||
public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView modelAndView) throws Exception {
|
||||
log.info("[postHandle][" + request + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed after complete request is finished
|
||||
**/
|
||||
@Override
|
||||
public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) throws Exception {
|
||||
if (ex != null)
|
||||
ex.printStackTrace();
|
||||
log.info("[afterCompletion][" + request + "][exception: " + ex + "]");
|
||||
}
|
||||
|
||||
private String getParameters(final HttpServletRequest request) {
|
||||
final StringBuffer posted = new StringBuffer();
|
||||
final Enumeration<?> e = request.getParameterNames();
|
||||
if (e != null)
|
||||
posted.append("?");
|
||||
while (e != null && e.hasMoreElements()) {
|
||||
if (posted.length() > 1)
|
||||
posted.append("&");
|
||||
final String curr = (String) e.nextElement();
|
||||
posted.append(curr).append("=");
|
||||
if (curr.contains("password") || curr.contains("answer") || curr.contains("pwd")) {
|
||||
posted.append("*****");
|
||||
} else {
|
||||
posted.append(request.getParameter(curr));
|
||||
}
|
||||
}
|
||||
|
||||
final String ip = request.getHeader("X-FORWARDED-FOR");
|
||||
final String ipAddr = (ip == null) ? getRemoteAddr(request) : ip;
|
||||
if (!Strings.isNullOrEmpty(ipAddr))
|
||||
posted.append("&_psip=" + ipAddr);
|
||||
return posted.toString();
|
||||
}
|
||||
|
||||
private String getRemoteAddr(final HttpServletRequest request) {
|
||||
final String ipFromHeader = request.getHeader("X-FORWARDED-FOR");
|
||||
if (ipFromHeader != null && ipFromHeader.length() > 0) {
|
||||
log.debug("ip from proxy - X-FORWARDED-FOR : " + ipFromHeader);
|
||||
return ipFromHeader;
|
||||
}
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
public class SessionTimerInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(SessionTimerInterceptor.class);
|
||||
|
||||
private static final long MAX_INACTIVE_SESSION_TIME = 5 * 10000;
|
||||
|
||||
@Autowired
|
||||
private HttpSession session;
|
||||
|
||||
/**
|
||||
* Executed before actual handler is executed
|
||||
**/
|
||||
@Override
|
||||
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
|
||||
log.info("Pre handle method - check handling start time");
|
||||
long startTime = System.currentTimeMillis();
|
||||
request.setAttribute("executionTime", startTime);
|
||||
if (UserInterceptor.isUserLogged()) {
|
||||
session = request.getSession();
|
||||
log.info("Time since last request in this session: {} ms", System.currentTimeMillis() - request.getSession().getLastAccessedTime());
|
||||
if (System.currentTimeMillis() - session.getLastAccessedTime() > MAX_INACTIVE_SESSION_TIME) {
|
||||
log.warn("Logging out, due to inactive session");
|
||||
SecurityContextHolder.clearContext();
|
||||
request.logout();
|
||||
response.sendRedirect("/spring-security-rest-full/logout");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed before after handler is executed
|
||||
**/
|
||||
@Override
|
||||
public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView model) throws Exception {
|
||||
log.info("Post handle method - check execution time of handling");
|
||||
long startTime = (Long) request.getAttribute("executionTime");
|
||||
log.info("Execution time for handling the request was: {} ms", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.SmartView;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
public class UserInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(UserInterceptor.class);
|
||||
|
||||
/**
|
||||
* Executed before actual handler is executed
|
||||
**/
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
|
||||
if (isUserLogged()) {
|
||||
addToModelUserDetails(request.getSession());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed before after handler is executed. If view is a redirect view, we don't need to execute postHandle
|
||||
**/
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model) throws Exception {
|
||||
if (model != null && !isRedirectView(model)) {
|
||||
if (isUserLogged()) {
|
||||
addToModelUserDetails(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used before model is generated, based on session
|
||||
*/
|
||||
private void addToModelUserDetails(HttpSession session) {
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
session.setAttribute("username", loggedUsername);
|
||||
log.info("user(" + loggedUsername + ") session : " + session);
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when model is available
|
||||
*/
|
||||
private void addToModelUserDetails(ModelAndView model) {
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
model.addObject("loggedUsername", loggedUsername);
|
||||
log.trace("session : " + model.getModel());
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
|
||||
}
|
||||
|
||||
public static boolean isRedirectView(ModelAndView mv) {
|
||||
|
||||
String viewName = mv.getViewName();
|
||||
if (viewName.startsWith("redirect:/")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
View view = mv.getView();
|
||||
return (view != null && view instanceof SmartView && ((SmartView) view).isRedirectView());
|
||||
}
|
||||
|
||||
public static boolean isUserLogged() {
|
||||
try {
|
||||
return !SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="WARN" />
|
||||
<logger name="org.springframework.transaction" level="WARN" />
|
||||
|
||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd"
|
||||
>
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/anonymous*" access="isAnonymous()"/>
|
||||
<intercept-url pattern="/login*" access="permitAll"/>
|
||||
<intercept-url pattern="/**" access="isAuthenticated()"/>
|
||||
|
||||
<csrf disabled="true"/>
|
||||
|
||||
<form-login login-page='/login.html' authentication-success-handler-ref="myAuthenticationSuccessHandler" authentication-failure-url="/login.html?error=true"/>
|
||||
|
||||
<logout delete-cookies="JSESSIONID"/>
|
||||
|
||||
<remember-me key="uniqueAndSecret" token-validity-seconds="86400"/>
|
||||
|
||||
</http>
|
||||
|
||||
<beans:bean id="myAuthenticationSuccessHandler" class="com.baeldung.security.MySimpleUrlAuthenticationSuccessHandler"/>
|
||||
|
||||
<authentication-manager id="authenticationManager">
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="user1" password="{noop}user1Pass" authorities="ROLE_USER" />
|
||||
<user name="admin1" password="{noop}admin1Pass" authorities="ROLE_ADMIN"/>
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
|
||||
<!-- <mvc:interceptors>
|
||||
<bean id="loggerInterceptor" class="com.baeldung.web.interceptor.LoggerInterceptor" />
|
||||
</mvc:interceptors> -->
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd" >
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Anonymous page</h1>
|
||||
|
||||
<a href="<c:url value="/login.html" />">To Login</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>This is the landing page for the admin</h1>
|
||||
|
||||
<security:authorize access="hasRole('ROLE_USER')">
|
||||
This text is only visible to a user
|
||||
<br/>
|
||||
</security:authorize>
|
||||
|
||||
<security:authorize access="hasRole('ROLE_ADMIN')">
|
||||
This text is only visible to an admin
|
||||
<br/>
|
||||
</security:authorize>
|
||||
|
||||
<a href="<c:url value="/logout" />">Logout</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>CSRF test on Origin</h1>
|
||||
<a href="transfer?accountNo=1234&amount=100">Transfer Money to John</a>
|
||||
|
||||
<form action="transfer" method="POST">
|
||||
<label>Account Number</label> <input name="accountNo" type="number"/>
|
||||
<label>Amount</label> <input name="amount" type="number"/>
|
||||
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>This is the homepage for the user</h1>
|
||||
|
||||
<security:authorize access="hasRole('ROLE_USER')">
|
||||
This text is only visible to a user
|
||||
<br />
|
||||
</security:authorize>
|
||||
|
||||
<security:authorize access="hasRole('ROLE_ADMIN')">
|
||||
This text is only visible to an admin
|
||||
<br />
|
||||
</security:authorize>
|
||||
|
||||
<a href="<c:url value="/logout" />">Logout</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Login</h1>
|
||||
|
||||
<form name='f' action="login" method='POST'>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>User:</td>
|
||||
<td><input type='text' name='username' value=''></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><input type='password' name='password' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Remember Me:</td>
|
||||
<td><input type="checkbox" name="remember-me" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input name="submit" type="submit" value="submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
xsi:schemaLocation="
|
||||
http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"
|
||||
>
|
||||
|
||||
<display-name>Spring MVC Custom Application</display-name>
|
||||
|
||||
<session-config>
|
||||
<session-timeout>1</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<!-- Spring root -->
|
||||
<context-param>
|
||||
<param-name>contextClass</param-name>
|
||||
<param-value>
|
||||
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>com.baeldung.spring</param-value>
|
||||
</context-param>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- Spring child -->
|
||||
<servlet>
|
||||
<servlet-name>mvc</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>mvc</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Spring Security -->
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- <welcome-file-list> -->
|
||||
<!-- <welcome-file>index.html</welcome-file> -->
|
||||
<!-- </welcome-file-list> -->
|
||||
|
||||
</web-app>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import com.baeldung.spring.SecSecurityConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { MvcConfig.class, SecSecurityConfig.class })
|
||||
@WebAppConfiguration
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.security.csrf;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import com.baeldung.web.dto.Foo;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
public abstract class CsrfAbstractIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private Filter springSecurityFilterChain;
|
||||
|
||||
MockMvc mvc;
|
||||
|
||||
//
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build();
|
||||
}
|
||||
|
||||
RequestPostProcessor testUser() {
|
||||
return user("user1").password("user1Pass").roles("USER");
|
||||
}
|
||||
|
||||
RequestPostProcessor testAdmin() {
|
||||
return user("admin").password("adminPass").roles("USER", "ADMIN");
|
||||
}
|
||||
|
||||
String createFoo() throws JsonProcessingException {
|
||||
return new ObjectMapper().writeValueAsString(new Foo(randomAlphabetic(6)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.security.csrf;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.baeldung.security.spring.SecurityWithoutCsrfConfig;
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class })
|
||||
public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception {
|
||||
mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAuth_whenAddFoo_thenCreated() throws Exception {
|
||||
mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.security.csrf;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.baeldung.security.spring.SecurityWithCsrfConfig;
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, MvcConfig.class })
|
||||
public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception {
|
||||
mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCsrf_whenAddFoo_thenCreated() throws Exception {
|
||||
mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.security.spring;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class ManualSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public ManualSecurityConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
// java config
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user1").password("{noop}user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(final WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Bean("authenticationManager")
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.mvcMatchers("/custom/login").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.headers().cacheControl().disable()
|
||||
.and()
|
||||
.csrf().disable()
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.baeldung.security.spring;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { MvcConfig.class, ManualSecurityConfig.class })
|
||||
public class ManualSecurityIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).apply(SecurityMockMvcConfigurers.springSecurity()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute custom login and access the endpoint
|
||||
*/
|
||||
@Test
|
||||
public void whenLoginIsSuccessFulThenEndpointCanBeAccessedAndCurrentUserPrinted() throws Exception {
|
||||
|
||||
mockMvc.perform(get("/custom/print"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
HttpSession session = mockMvc.perform(post("/custom/login").param("username", "user1").param("password", "user1Pass"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
|
||||
mockMvc.perform(get("/custom/print").session((MockHttpSession) session))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.security.spring;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public SecurityWithCsrfConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Bean("authenticationManager")
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(final WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/auth/admin/*").hasAnyRole("ROLE_ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.headers().cacheControl().disable()
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.security.spring;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public SecurityWithoutCsrfConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Bean("authenticationManager")
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(final WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/auth/admin/*").hasAnyRole("ROLE_ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.headers().cacheControl().disable()
|
||||
.and()
|
||||
.csrf().disable()
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.baeldung.security.spring.SecurityWithoutCsrfConfig;
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class })
|
||||
public class LoggerInterceptorIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
|
||||
@Autowired
|
||||
MockHttpSession session;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* After execution of HTTP GET logs from interceptor will be displayed in
|
||||
* the console
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testInterceptors() throws Exception {
|
||||
mockMvc.perform(get("/login.html"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.baeldung.security.spring.SecurityWithoutCsrfConfig;
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class })
|
||||
@WithMockUser(username = "admin", roles = { "USER", "ADMIN" })
|
||||
public class SessionTimerInterceptorIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* After execution of HTTP GET logs from interceptor will be displayed in
|
||||
* the console
|
||||
*/
|
||||
@Test
|
||||
public void testInterceptors() throws Exception {
|
||||
HttpSession session = mockMvc.perform(get("/auth/foos"))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
Thread.sleep(51000);
|
||||
mockMvc.perform(get("/auth/foos").session((MockHttpSession) session))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.web.interceptor;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.baeldung.security.spring.SecurityWithoutCsrfConfig;
|
||||
import com.baeldung.spring.MvcConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class })
|
||||
@WithMockUser(username = "admin", roles = { "USER", "ADMIN" })
|
||||
public class UserInterceptorIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
|
||||
@Autowired
|
||||
MockHttpSession session;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* After execution of HTTP GET logs from interceptor will be displayed in
|
||||
* the console
|
||||
*/
|
||||
@Test
|
||||
public void testInterceptors() throws Exception {
|
||||
mockMvc.perform(get("/auth/foos"))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
}
|
||||
|
||||
}
|
||||
13
spring-security-modules/spring-security-web-mvc-custom/src/test/resources/.gitignore
vendored
Normal file
13
spring-security-modules/spring-security-web-mvc-custom/src/test/resources/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
*.class
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
Reference in New Issue
Block a user