
Authorization: Process of deciding whether an user is allowed to perform an activity within the application.
Spring security supports more then 20 Models for authentication :
X.509 client certificate exchange
LDAP Authentication
OpenID authentication
Java Open Source Single Sign On
......
1. TOOLS AND ENV
IDE : Spring Tool Suite 3.7.3 JDK :
1.8 Tomcat : 8.0.18
Spring : 4.2.6.RELEASE
2. POM.XML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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/maven-v4_0_0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>org.junjun.spring.tutorials</groupId> | |
<artifactId>spring-mvc-web-security</artifactId> | |
<version>1.0.0</version> | |
<properties> | |
<java.version>1.8</java.version> | |
<org.springframework.version>4.2.6.RELEASE</org.springframework.version> | |
<org.spring.security.version>4.1.0.RELEASE</org.spring.security.version> | |
<slf4j.version>1.7.10</slf4j.version> | |
</properties> | |
<dependencies> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-context</artifactId> | |
<version>${org.springframework.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-webmvc</artifactId> | |
<version>${org.springframework.version}</version> | |
</dependency> | |
<!-- Spring JAXB support --> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-oxm</artifactId> | |
<version>${org.springframework.version}</version> | |
</dependency> | |
<!-- Spring Security Web --> | |
<dependency> | |
<groupId>org.springframework.security</groupId> | |
<artifactId>spring-security-web</artifactId> | |
<version>${org.spring.security.version}</version> | |
</dependency> | |
<!-- Spring Security Config --> | |
<dependency> | |
<groupId>org.springframework.security</groupId> | |
<artifactId>spring-security-config</artifactId> | |
<version>${org.spring.security.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>javax.validation</groupId> | |
<artifactId>validation-api</artifactId> | |
<version>1.1.0.Final</version> | |
</dependency> | |
<dependency> | |
<groupId>org.hibernate</groupId> | |
<artifactId>hibernate-validator</artifactId> | |
<version>5.1.2.Final</version> | |
</dependency> | |
<dependency> | |
<groupId>org.slf4j</groupId> | |
<artifactId>slf4j-log4j12</artifactId> | |
<version>1.7.5</version> | |
</dependency> | |
<dependency> | |
<groupId>javax.servlet</groupId> | |
<artifactId>javax.servlet-api</artifactId> | |
<version>3.1.0</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>javax.servlet.jsp</groupId> | |
<artifactId>javax.servlet.jsp-api</artifactId> | |
<version>2.3.1</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>javax.servlet</groupId> | |
<artifactId>jstl</artifactId> | |
<version>1.2</version> | |
</dependency> | |
<dependency> | |
<groupId>com.fasterxml.jackson.core</groupId> | |
<artifactId>jackson-databind</artifactId> | |
<version>2.7.4</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-war-plugin</artifactId> | |
<configuration> | |
<failOnMissingWebXml>false</failOnMissingWebXml> | |
</configuration> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<configuration> | |
<source>${java.version}</source> | |
<target>${java.version}</target> | |
<compilerArgument>-Xlint:all</compilerArgument> | |
<showWarnings>true</showWarnings> | |
<showDeprecation>true</showDeprecation> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
spring-security-web and spring-security-config added
3. SECURITY CONFIG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.junjun.spring.tutorials.config; | |
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; | |
public class SecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.junjun.spring.tutorials.config; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.beans.factory.annotation.Qualifier; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | |
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |
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.core.userdetails.UserDetailsService; | |
@Configuration | |
@EnableWebSecurity | |
public class SecurityConfig extends WebSecurityConfigurerAdapter { | |
@Autowired | |
@Qualifier("springUserDetailService") | |
UserDetailsService userDetailsService; | |
@Autowired | |
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { | |
auth.authenticationProvider(authenticationProvider()); | |
} | |
@Bean | |
public DaoAuthenticationProvider authenticationProvider() { | |
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); | |
authenticationProvider.setUserDetailsService(userDetailsService); | |
// set below if your password is encoded | |
// authenticationProvider.setPasswordEncoder(passwordEncoder); | |
return authenticationProvider; | |
} | |
@Override | |
protected void configure(HttpSecurity http) throws Exception { | |
http.authorizeRequests().antMatchers("/todo/**").access("hasRole('ROLE_WEB')"); | |
http.formLogin().loginPage("/login"); | |
// to custom parameter name : | |
// http.formLogin().usernameParameter("user_name"); | |
http.logout().logoutUrl("/logout"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.junjun.spring.tutorials.config; | |
import org.springframework.web.context.WebApplicationContext; | |
import org.springframework.web.servlet.DispatcherServlet; | |
import org.springframework.web.servlet.FrameworkServlet; | |
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; | |
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { | |
@Override | |
protected Class<?>[] getRootConfigClasses() { | |
return new Class[] { AppConfig.class, SecurityConfig.class }; | |
} | |
@Override | |
protected Class<?>[] getServletConfigClasses() { | |
return new Class<?>[] { WebConfig.class }; | |
} | |
@Override | |
protected String[] getServletMappings() { | |
return new String[] { "/" }; | |
} | |
@Override | |
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) { | |
DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext); | |
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); | |
return dispatcherServlet; | |
} | |
} | |
1. SecurityWebAppInitializer equals below line in web.xml
<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>
3. ServletInitializer to add SecurityConfig to root configuration
4. USER DETAILS SERVICE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.junjun.spring.tutorials.service.impl; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
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.security.core.userdetails.UsernameNotFoundException; | |
import org.springframework.stereotype.Service; | |
@Service("springUserDetailService") | |
public class UserDetailsServiceImpl implements UserDetailsService { | |
private Map<String, String> users = new HashMap<>(); | |
public UserDetailsServiceImpl() { | |
users.put("springuser", "springpassword"); | |
} | |
@Override | |
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |
User user = null; | |
if (users.keySet().contains(username)) { | |
user = new User(username, users.get(username), getGrantedAuthorities(username)); | |
} else { | |
throw new UsernameNotFoundException("username [" + username + "] not found"); | |
} | |
return user; | |
} | |
private List<GrantedAuthority> getGrantedAuthorities(String username) { | |
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); | |
// here ROLE_USER is hard coded , but system can load user role from DB | |
// by user name and add to the list | |
authorities.add(new SimpleGrantedAuthority("ROLE_WEB")); | |
return authorities; | |
} | |
} |
DaoAuthenticationProvider would use user details service to load user account and match with given password.
5. AUTHORIZATION CONTROLLER
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.cn.junjun.spring.sample.web.controller; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestMethod; | |
@Controller | |
public class AuthController { | |
@RequestMapping(value = "/login", method = RequestMethod.GET) | |
public String displayLoginPage() { | |
return "login"; | |
} | |
@RequestMapping(value = "/login", method = RequestMethod.POST) | |
public String login() { | |
return "forward:/rest/todo/list"; | |
} | |
@RequestMapping(value = "/logout", method = RequestMethod.POST) | |
public String logout() { | |
return "/login"; | |
} | |
} |
logout must be POST then it would be registered to spring security to clear authorization context.
6. JSP AND JAVASCRIPT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ page language="java" contentType="text/html; charset=UTF-8" | |
pageEncoding="UTF-8"%> | |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> | |
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> | |
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<meta name="description" content="spring"> | |
<meta name="keywords" content="spring"> | |
<meta name="_csrf" content="${_csrf.token}" /> | |
<meta name="_csrf_header" content="${_csrf.headerName}" /> | |
<title></title> | |
<link rel="stylesheet" | |
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> | |
</head> | |
<body> | |
<header class="navbar navbar-default navbar-fixed-top bs-docs-nav" | |
role="banner"> | |
<div class="container"> | |
<nav class="collapse navbar-collapse bs-navbar-collapse"> | |
<ul class="nav navbar-nav navbar-right"> | |
<li><a id="link-logout" href="javascript:;"> Logout </a></li> | |
</ul> | |
</nav> | |
</div> | |
</header> | |
<div class="container" style="padding-top: 10%"> | |
<div class="row"> | |
<form:form id="form-todo" class="form-horizontal" | |
modelAttribute="newToDo" action=""> | |
<input name="${_csrf.parameterName}" type="hidden" | |
value="${_csrf.token}"> | |
<div class="form-group"> | |
<div class="col-md-offset-2 col-md-6"> | |
<form:input id="todoContent" class="form-control" path="content" | |
placeholder="" /> | |
</div> | |
<div class="col-md-2"> | |
<button id="rest-create-btn" class="btn btn-success btn-block">Create</button> | |
</div> | |
<label for="todoContent" class="col-md-4 control-label" | |
style="text-align: left;"><spring:bind path="content"> | |
<c:if test="${status.error}"> | |
<form:errors path="content" class="text-danger" /> | |
</c:if> | |
</spring:bind></label> | |
</div> | |
</form:form> | |
</div> | |
<div class="row"> | |
<div class="col-md-offset-2 col-md-10"> | |
<ul id="ul-todo-list"> | |
<c:forEach items="${toDoList}" var="toDo"> | |
<li>${toDo.createdDateDisplay} : ${toDo.content}</li> | |
</c:forEach> | |
</ul> | |
</div> | |
</div> | |
<input type="hidden" id="rest-url-create" | |
value="${pageContext.request.contextPath}/api/todo/create" /> | |
</div> | |
<form id="form-logout" | |
action="${pageContext.request.contextPath}/logout" method="post"> | |
<input name="${_csrf.parameterName}" type="hidden" | |
value="${_csrf.token}"> | |
</form> | |
<script src="http://code.jquery.com/jquery-latest.min.js"></script> | |
<script | |
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | |
<script src="${pageContext.request.contextPath}/js/todo/rest/list.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
$(document).ready(function() { | |
var token = $("meta[name='_csrf']").attr("content"); | |
var header = $("meta[name='_csrf_header']").attr("content"); | |
$(document).ajaxSend(function(e, xhr, options) { | |
xhr.setRequestHeader(header, token); | |
}); | |
$.fn.serializeObject = function() | |
{ | |
var o = {}; | |
var a = this.serializeArray(); | |
$.each(a, function() { | |
if (o[this.name] !== undefined) { | |
if (!o[this.name].push) { | |
o[this.name] = [o[this.name]]; | |
} | |
o[this.name].push(this.value || ""); | |
} else { | |
o[this.name] = this.value || ""; | |
} | |
}); | |
return o; | |
}; | |
$(document).on("#form-todo").submit(function(event) { | |
event.preventDefault(); | |
return false; | |
}); | |
$(document).on("click", "#link-logout", function(event) { | |
event.preventDefault() | |
$("#form-logout")[0].submit(); | |
}); | |
$(document).on("click", "#rest-create-btn", function() { | |
var form = $("#form-todo"); | |
var url = $("#rest-url-create").val(); | |
var data = JSON.stringify(form.serialize()); | |
data = JSON.stringify(form.serializeObject()); | |
$.ajax({ | |
type : "POST", | |
url : url, | |
data : data, | |
contentType: "application/json; charset=utf-8", | |
dataType: "json", | |
success : function(response) { | |
var output="<li>" + response.date + " : " +response.content + "</li>"; | |
$("#ul-todo-list").append(output); | |
$("#todoContent").val(""); | |
} | |
}); | |
}); | |
}); | |
})(); |
CSRF token is per session.
7. RUN THE APPLICATION
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No HttpSession currently exists | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created. | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /' doesn't match 'POST /logout | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /' doesn't match 'POST /login | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' | |
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/todo/**' | |
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'delegatingApplicationListener' | |
DEBUG: org.springframework.security.web.FilterChainProxy - / reached end of additional filter chain; proceeding with original chain | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/04-spring-mvc-web-security/] | |
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path / | |
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public java.lang.String org.junjun.spring.tutorials.web.controller.HomeController.loadHomePage()] | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'homeController' | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/04-spring-mvc-web-security/] is: -1 | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'redirect:/todo/list' | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.RedirectView: name 'redirect:/todo/list'; URL [/todo/list]] in DispatcherServlet with name 'dispatcher' | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'requestDataValueProcessor' | |
DEBUG: org.springframework.security.web.header.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@67c9cf6f | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'delegatingApplicationListener' | |
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally | |
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No HttpSession currently exists | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created. | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /todo/list' doesn't match 'POST /logout | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /todo/list' doesn't match 'POST /login | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' | |
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /todo/list at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/todo/list'; against '/todo/**' | |
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /todo/list; Attributes: [hasRole('ROLE_WEB')] | |
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS | |
DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@7a5dbcff, returned: -1 | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'delegatingApplicationListener' | |
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point | |
org.springframework.security.access.AccessDeniedException: Access is denied | |
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) | |
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) | |
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) | |
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:112) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:206) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) | |
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) | |
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:106) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) | |
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) | |
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) | |
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) | |
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) | |
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) | |
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) | |
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) | |
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) | |
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) | |
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) | |
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) | |
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) | |
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) | |
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) | |
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) | |
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528) | |
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099) | |
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670) | |
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520) | |
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476) | |
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) | |
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) | |
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) | |
at java.lang.Thread.run(Thread.java:745) | |
DEBUG: org.springframework.security.web.util.matcher.AndRequestMatcher - Trying to match using Ant [pattern='/**', GET] | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request '/todo/list' matched by universal pattern '/**' | |
DEBUG: org.springframework.security.web.util.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=Ant [pattern='/**/favicon.ico']] | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/todo/list'; against '/**/favicon.ico' | |
DEBUG: org.springframework.security.web.util.matcher.NegatedRequestMatcher - matches = true | |
DEBUG: org.springframework.security.web.util.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.HeaderContentNegotiationStrategy@1d6ca2f, matchingMediaTypes=[application/json], useEquals=false, ignoredMediaTypes=[*/*]]] | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - httpRequestMediaTypes=[text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8] | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Processing text/html | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - application/json .isCompatibleWith text/html = false | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Processing application/xhtml+xml | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - application/json .isCompatibleWith application/xhtml+xml = false | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Processing application/xml;q=0.9 | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - application/json .isCompatibleWith application/xml;q=0.9 = false | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Processing */*;q=0.8 | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Ignoring | |
DEBUG: org.springframework.security.web.util.matcher.MediaTypeRequestMatcher - Did not match any media types | |
DEBUG: org.springframework.security.web.util.matcher.NegatedRequestMatcher - matches = true | |
DEBUG: org.springframework.security.web.util.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]] | |
DEBUG: org.springframework.security.web.util.matcher.NegatedRequestMatcher - matches = true | |
DEBUG: org.springframework.security.web.util.matcher.AndRequestMatcher - All requestMatchers returned true | |
DEBUG: org.springframework.security.web.savedrequest.HttpSessionRequestCache - DefaultSavedRequest added to Session: DefaultSavedRequest[http://localhost:8080/04-spring-mvc-web-security/todo/list] | |
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Calling Authentication entry point. | |
DEBUG: org.springframework.security.web.DefaultRedirectStrategy - Redirecting to 'http://localhost:8080/04-spring-mvc-web-security/login' | |
DEBUG: org.springframework.security.web.header.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@67c9cf6f | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. | |
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@2ae61e6. A new one will be created. | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /login' doesn't match 'POST /logout | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /login' doesn't match 'POST /login | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' | |
DEBUG: org.springframework.security.web.savedrequest.DefaultSavedRequest - pathInfo: both null (property equals) | |
DEBUG: org.springframework.security.web.savedrequest.DefaultSavedRequest - queryString: both null (property equals) | |
DEBUG: org.springframework.security.web.savedrequest.DefaultSavedRequest - requestURI: arg1=/04-spring-mvc-web-security/todo/list; arg2=/04-spring-mvc-web-security/login (property not equals) | |
DEBUG: org.springframework.security.web.savedrequest.HttpSessionRequestCache - saved request doesn't match | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' | |
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9056f12c: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@380f4: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 9A7277AD4A11B571CDE48B9AC371F279; Granted Authorities: ROLE_ANONYMOUS' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' | |
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login'; against '/todo/**' | |
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted | |
DEBUG: org.springframework.security.web.FilterChainProxy - /login reached end of additional filter chain; proceeding with original chain | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/04-spring-mvc-web-security/login] | |
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /login | |
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public java.lang.String org.junjun.spring.tutorials.web.controller.AuthController.displayLoginPage()] | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'authController' | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/04-spring-mvc-web-security/login] is: -1 | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'login' | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'login'; URL [/WEB-INF/jsp/login.jsp]] in DispatcherServlet with name 'dispatcher' | |
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'requestDataValueProcessor' | |
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/jsp/login.jsp] in InternalResourceView 'login' | |
DEBUG: org.springframework.security.web.header.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@67c9cf6f | |
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. | |
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request | |
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally | |
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed |
8. LOGIN SUCCESS
9. SOURCE CODE
https://github.com/junjun-dachi/spring-tutorials/tree/master/04-spring-mvc-web-security
Reference :
1. http://docs.spring.io/spring-security/site/docs/current/reference/html/jc.html
2. https://spring.io/blog/2013/07/04/spring-security-java-config-preview-method-security/
3. https://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/
4. http://stackoverflow.com/questions/25276152/spring-security-java-config-custom-authenticationprovider-and-userdetailsservi
5. http://stackoverflow.com/questions/22453550/custom-authentication-provider-not-being-called
No comments:
Post a Comment