When CSRF enable in Spring Security, Access denied 403 - spring

In my Spring application in spring security configuration file when csrf is enable
(<security:csrf/>)
and try to submit login form then Access denied page 403 appear (or)
(Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.) exception (when access-denied-handler not present)
"But if I don't enable CSRF in spring security configuration file then everything work perfectly."
Here my codes when CSRF enable
pom.xml (all the versions)
<properties>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
</properties>
spring-security.xml
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()"/>
<!-- access denied page -->
<security:access-denied-handler error-page="/403"/>
<security:form-login
login-page="/login" default-target-url="/loginSuccess" authentication-failure-url="/loginError?error"/>
<!-- enable csrf protection-->
<security:csrf/>
</security:http>
<!-- Select users and user_roles from database -->
<security:authentication-manager>
<security:authentication-provider>
<!--<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username,password, enabled from registration where username=?"
authorities-by-username-query="select username, role from registration where username=?"/> -->
<security:user-service>
<security:user name="test" password="test" authorities="ROLE_USER" />
<security:user name="test1" password="test1" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
Controller
#Controller
public class MainController {
#RequestMapping(value={"/login"})
public ModelAndView loginPage(){
ModelAndView model = new ModelAndView("login");
return model;
}
#RequestMapping(value={"/loginSuccess"},method=RequestMethod.POST)
public ModelAndView loginSuccess(Principal principal,HttpServletRequest request,HttpSession session){
ModelAndView model = new ModelAndView("success");
//Testing.......
String name = principal.getName();
model.addObject("username", name);
session = request.getSession();
session.setAttribute("USER", "system");
return model;
}
login.jsp
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%#page session="true"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>login Page</title>
<!-- <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body onload='document.loginForm.username.focus();'>
<h1>Spring Security Login Form (Database Authentication)</h1>
<div>
<h3>Login with Username and Password</h3>
<c:if test="${not empty error}">
<div>${error}</div>
</c:if>
<form name="loginForm" action="j_spring_security_check" method="post">
<table>
<tr>
<td>Username</td>
<td><input type="text" name=j_username></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name=j_password></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" /></td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
</div>
</body>
</html>
403.jsp
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h1>HTTP Status 403 - Access is denied</h1>
<c:choose>
<c:when test="${empty username}">
<h2>You do not have permission to access this page!</h2>
</c:when>
<c:otherwise>
<h2>Username : ${username} <br/>You do not have permission to access this page!</h2>
</c:otherwise>
</c:choose>
</body>
</html>
Output:
HTTP Status 403 - Access is denied
Username : ${username}
You do not have permission to access this page!
Please help.
Solution
Controller:
#RequestMapping(value={"/","/loginSuccess"},method=RequestMethod.GET)
public ModelAndView loginSuccess()
web.xml
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
Due to of default page

I think you are doing an ajax request once you submit the form. In that case, you have to pass csrf token in the header.
something like,
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
var headers ={};
headers[header]=token;
var headerObj = {};
headerObj['headers']=headers;
$http.post("http://xyz",request,headerObj);
In order to enable csrf only for a particular url, You can do something like this
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new RequestMatcher() {
#Override
public boolean matches(HttpServletRequest request) {
return request.getServletPath().contains("/xyz");
}
});
}
}

Related

csrf security blocks http requests

I want to use http post to post data from jsp page to my controller .the problem is that when I enable csrf the request wasn't sent but I want to enable csrf can any one help me ?
home.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<title>Insert title here</title>
</head>
<body>
hello there !!!<br>
<button type="button" onclick="location.href='${pageContext.request.contextPath}/create';"> start workflow</button> <br>
<button type="button" onclick="location.href='${pageContext.request.contextPath}/workflows';"> View Workflows</button> <br>
<button type="button" onclick="sendDataWithJson();"> View data</button> <br>
login
<p>Parameter from home ${pageContext.request.userPrincipal.name}</p>
</body>
<script type="text/javascript">
function success(data){
alert("success");
}
function error(data){
alert("error");
}
function sendDataWithJson(){
$.ajax({
type: 'POST',
url: '<c:url value="/sendmessage" />',
data: JSON.stringify({"text":"bla bla bla","name":"MED"}),
success:success,
error:error,
contentType: "application/json",
dataType: "json"
});
}
</script>
</html>
springsecurity.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd">
<security:authentication-manager>
<security:ldap-authentication-provider
user-search-filter="(uid={0})" user-search-base="ou=users"
group-search-filter="(uniqueMember={0})" group-search-base="ou=groups"
group-role-attribute="cn" role-prefix="ROLE_" />
</security:authentication-manager>
<security:ldap-server url="ldap://localhost:8389/o=mojo"
manager-dn="uid=admin,ou=system" manager-password="secret" />
<security:http use-expressions="true">
<security:intercept-url pattern="/" access="permitAll"/>
<security:intercept-url pattern="/next" access="permitAll" />
<security:intercept-url pattern="/workflows" access="isAuthenticated()"/>
<security:intercept-url pattern="/getmessages" access="isAuthenticated()"/>
<security:intercept-url pattern="/sendmessage" access="permitAll"/>
<security:form-login login-page="/login"
login-processing-url="/login"
authentication-failure-url="/login.html?error=true"
username-parameter="username"
password-parameter="password"
/>
<security:csrf/>
</security:http>
</beans>
controller
#RequestMapping( value = "/sendmessage" , method=RequestMethod.POST , produces="application/json")
#ResponseBody
public Map<String, Object> getData(#RequestBody Map<String, Object> data){
String text=(String) data.get("text");
String name=(String) data.get("name");
System.out.println(text+","+name);
Map<String, Object>rval = new HashMap<String, Object>();
rval.put("success",true);
return rval;
}
You can add the csrf value to html when you are using jsp:
<meta name="_csrf_param" content="${_csrf.parameterName}"/>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
this will render the crsf value from session.
and now you are using ajax, you should add the csrf token in header, you can extend the jquery:
$(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);
});
});

No mapping found for HTTP request with URI [/.../j_spring_security_check] in DispatcherServlet with name 'servlet-dispatcher'

Plop,
Spring version: 4.0.2.RELEASE
Spring Security Version: 4.0.2.RELEASE
DB PostgreSQL Version: 9.4-1202-jdbc42
I'm trying to acces to my home page with a secure connection using spring-security.
When I try to connect with login/password I've got this error:
WARNING: No mapping found for HTTP request with URI
[/web-client-smarteo/j_spring_security_check] in DispatcherServlet
with name 'servlet-dispatcher'
When I submit with log/pass it's get me to:
http://localhost:8080/web-client-smarteo/j_spring_security_check?username=alfacamp&password=alfacam&submit=&%24%7B_csrf.parameterName%7D=%24%7B_csrf.token%7D
And show
HTTP 404 The requested ressource is unvailable
Details of my sample:
UPDATE
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Spring Security Filter -->
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>servlet-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servlet-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
dispatcher-servlet.xml
<mvc:annotation-driven />
<context:component-scan base-package="com.smarteo.laugustoni.*" />
[...]
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/vues/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
spring-security.xml
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/welcome**" access="hasRole('CUSTOMER')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/connection"
default-target-url="/welcome"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/connection?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/connection?logout" />
<!-- enable csrf protection -->
<csrf/>
</http>
<!-- Select users and user_roles from database -->
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select usr_name,usr_password from smarteo_user where usr_name=?"
authorities-by-username-query=
"select usr_name, usr_role from smarteo_user where usr_name =? " />
</authentication-provider>
</authentication-manager>
ConnectionController.java
package com.smarteo.laugustoni.controller;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
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.servlet.ModelAndView;
import com.smarteo.laugustoni.services.User.IServiceUser;
#Controller
public class ConnectionController {
#RequestMapping(value={"/", "/welcome**"}, method = RequestMethod.GET)
public String defaultPage(ModelMap pModel)
{
return "connection";
}
#RequestMapping(value="/connexion", method = RequestMethod.GET)
public ModelAndView connection(
#RequestParam(value="error", required = false) String error,
#RequestParam(value = "logout", required = false)String logout)
{
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username and password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("connection");
return model;
}
Thanks for helping.
EDIT 1
connection.jsp
<%#page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page session="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<form name="loginForm" action="/j_spring_security_check">
<!-- TextBox Section -->
<div class="input-group visible">
<spring:message code="connection.label.account"/>
<input name="username" path="username" placeholder="Nom du compte" type="text" class="form-control" aria-describedby="basic-addon1"/>
<div class="alert alert-danger" role="alert"><form:errors path="username" cssclass="error"/></div>
</div><br />
<div class="input-group visible">
<spring:message code="connection.label.password"/>
<input name="password" path="password" placeholder="Mot de passe" type="password" class="form-control" aria-describedby="basic-addon1"/><br />
<div class="alert alert-danger" role="alert"><form:errors path="password" cssclass="error"/></div>
</div><br />
<!-- TextBoxSection -->
<!-- Button Section -->
<button name="submit" type="submit" class="btn btn-default visible">
<spring:message code="connection.button.label.connect"/>
</button><br />
<!-- Button Section -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</body>
EDIT 2:
I'm now using:
<form name="loginForm" action="<c:url value='/login' />" method="POST" >
I had also change my spring-security.xml:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/welcome**" access="hasRole('CUSTOMER')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
default-target-url="/welcome**"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf/>
</http>
And my ConnectionController.java
#RequestMapping(value = "/welcome**", method = RequestMethod.GET)
public String defaultPage()
{
return "home";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout)
{
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username and password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("connection");
return model;
}
#RequestMapping(value = "/403", method = RequestMethod.GET)
public ModelAndView accesssDenied() {
ModelAndView model = new ModelAndView();
//check if user is login
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
model.addObject("username", userDetail.getUsername());
}
model.setViewName("403");
return model;
}
I'm now getting State HTTP 405 - Request method 'POST' not supported when I'm trying to login
My problem was due to spring security version.
Indeed for 4.x you have to put the csrf in your form action.
My sources modified with the solution:
connection.jsp
<form name="loginForm" action="<c:url value='/login?${_csrf.parameterName}=${_csrf.token} }' />" method="POST" >
<!-- TextBox Section -->
<div class="input-group visible">
<spring:message code="connection.label.account"/>
<input name="username" path="username" placeholder="Nom du compte" type="text" class="form-control" aria-describedby="basic-addon1"/>
<!--<div class="alert alert-danger" role="alert"><form:errors path="username" cssclass="error"/></div>-->
</div><br />
<div class="input-group visible">
<spring:message code="connection.label.password"/>
<input name="password" path="password" placeholder="Mot de passe" type="password" class="form-control" aria-describedby="basic-addon1"/><br />
<!--<div class="alert alert-danger" role="alert"><form:errors path="password" cssclass="error"/></div>-->
</div><br />
<!-- TextBoxSection -->
<!-- Button Section -->
<input name="submit" type="submit" class="btn btn-default visible" value=<spring:message code="connection.button.label.connect"/> />
<br />
<!-- Button Section -->
</form>
spring-security.xml:
<http auto-config="true" >
<intercept-url pattern="/welcome**" access="hasRole('CUSTOMER')" />
<form-login login-page="/login"
default-target-url="/welcome"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/403" />
<!-- enable csrf protection -->
<csrf disabled="true"/>
</http>

why authentication-failure-url in spring security not working

I am using spring security in my website, but when I used custom login form (JSF form), and user entered bad credentials, authentication-failure-url is not working and user is not forwarded to failed.xhtml, but index.xhtml is appeared
I don't know the reason, please help:
applicationContext.xml:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<context:component-scan base-package="com.myspring" />
<context:annotation-config />
<!-- beans configuration -->
<beans:bean id="userBo" class="com.myspring.user.bo.impl.UserBoImpl" />
<!-- security configuration -->
<http auto-config="true">
<intercept-url pattern="/login.xhtml" access="permitAll" />
<intercept-url pattern="/index.xhtml" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/authenticated.xhtml" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/views/admin/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login.xhtml" default-target-url="/authenticated.xhtml"
authentication-failure-url="/failed.xhtml" />
<logout invalidate-session="true" delete-cookies="true" logout-success-url="/"/>
<csrf disabled="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="user1" password="user1Pass" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
login.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
<div style="">
<h:form id="loginFormId" prependId="false">
<div id="loginFieldsPnlId">
<div id="loginFieldUsrContId">
<h:outputText id="outTxtUserNameId" value="Username: "
name="outTxtUserNameNm"></h:outputText>
<h:inputText id="userName" required="true"
value="#{loginController.userName}"
requiredMessage="Please enter username"></h:inputText>
<h:outputLabel id="outLblUserNameId" for="userName"
name="outLblUserNameNm"></h:outputLabel>
</div>
<div id="loginFieldPassContId">
<h:outputText id="outTxtPasswordId" value="Password: "
name="outTxtPasswordNm"></h:outputText>
<h:inputSecret id="password" required="true"
value="#{loginController.password}"
requiredMessage="Please enter password" name="inTxtPasswordNm"></h:inputSecret>
<h:outputLabel id="outLblPasswordId" for="password"
name="outLblPasswordNm"></h:outputLabel>
</div>
</div>
<div id="loginBtnPanelId">
<h:commandButton id="btnLoginId" value="Login"
action="#{loginController.login}" styleClass="loginPanelBtn"></h:commandButton>
<h:commandButton id="btnCancelId" value="Cancel"
action="#{loginController.cancel}" styleClass="loginPanelBtn"
immediate="true" update="loginFormId"></h:commandButton>
</div>
</h:form>
</div>
<div>
<h:messages></h:messages>
</div>
</h:body>
</html>
and this is the loginController with login method:
package com.myspring.controllers;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
#ManagedBean
#SessionScoped
public class LoginController {
private String userName;
private String password;
#ManagedProperty(value="#{authenticationManager}")
private AuthenticationManager authenticationManager = null;
public String login() {
try {
Authentication request = new UsernamePasswordAuthenticationToken(this.getUserName(), this.getPassword());
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
} catch (AuthenticationException e) {
e.printStackTrace();
return "failed";
}
return "success";
}
public String logout(){
SecurityContextHolder.clearContext();
return "loggedout";
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public String cancel()
{
return "";
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
also I will add project structure:
Due to the fact that you are using JSF you are basically bypassing the login (and logout) functionality provided by Spring Security. Your LoginController is basically replacing that, due to that your sec:login-form and sec:legato are pretty much useless.
The solution is simple don't use JSF, you can still use Facelets to render your page, but simply include a normal form tag which posts to /login instead of an h:form tag and you can remove your LoginController.
Note: If your application is not the root application (i.e. mapped to /) you need to include the /context-path into your URL. So instead of /login use /context-path/login.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
<div style="">
<form id="loginFormId" method="post" action="/login">
<div id="loginFieldsPnlId">
<div id="loginFieldUsrContId">
<label>Username:<label>
<input type="text" id="username" name="username" />
</div>
<div id="loginFieldPassContId">
<label>Password:<label>
<input type="password" id="password" name="password" />
</div>
</div>
<div id="loginBtnPanelId">
<button>Login</button>
</div>
</form>
</div>
</h:body>
</html>
If you still want to use JSF and the LoginController then don't directly use the AuthenticationManager but forward the request to the /login URL that way Spring Security will take over after JSF has done the required validation.

Spring security repeated redirects

I am using spring security in my application. I want the user to be logged in first before accessing any pages on the server, hence i am taking the redirect approach. But the redirect seems to be in an infinite loop cause it redirects me to the login page no matter how many times i submit the page. I tried debugging and the request always hits the GET instead of the POST method as i expected. I am using LDAP authentication using the details entered by the user on the form. Here is the code in the security context xml . Can someone point me in the right direction.
<http pattern="/resources/**" security="none" />
<http auto-config="true">
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/login" default-target-url="/dashboard"
authentication-failure-url="/loginfailed" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
When i remove the
<form-login login-page="/login" default-target-url="/dashboard"
authentication-failure-url="/loginfailed" />
it defaults to spring login page and it works but i have to use the user credentials from the configuration xml as opposed to LDAP credentials.
Edit**
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<link rel="stylesheet" href="${contextPath}/resources/css/styles.css" type="text/css">
<h2 style="text-align:center">Login to continue to Application</h2>
<div align="center" class="div">
<form:form method="POST" modelAttribute="login" action="authenticate">
<table>
<tr>
<td><form:label path="username" class="label">Username:</form:label></td>
<td><form:input path="username" class="input"/></td>
<td><form:errors path="username" class="error" /></td>
</tr>
<tr>
<td><form:label path="password" class="label">Password:</form:label></td>
<td><form:password path="password" class="input"/></td>
<td><form:errors path="password" class="error"/></td>
</tr>
<tr>
<td colspan="2" align="right"><input type="submit"
value="Login" class="button"/></td>
</tr>
</table>
</form:form>
</div>
thanks
Sree
#sri
as mentioned in your code i can see that you have intercepted the URL "/login*"
now any url with login at the end will be intercepted by spring security and after that you have to put the correct credentials....
now After giving credentials your are redirected to page /login
now its clear that again our url is ending with login hence it is intercepted again by spring security ...
thats why the loop continues....
Possible Solution
this may work for you,
just put the following code below <http pattern="/resources/**" security="none" /> tag as shown:
code:
<http pattern="/resources/**" security="none" />
<http pattern="/Login.html" security="none" />
Ok. Finally i got to a working state. Here are the changes i made to the security context xml
<intercept-url pattern="/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
the url regex change. And also the action in my login.jsp is now
action="/login/authenticate"
and finally the controller request mapping path is updated.
Hope this helps anyone who has a similar issue. I am yet to discover if this is the right approach to achieve it but works for now.
-Sree

Spring Custom AuthenticationProvider never invoked - 404 error on http://localhost:8080/igloo/j_spring_security_check

I am trying to get an example of custom j_spring_security_check working on tomcat 7.0.47. Spring MVC goes to login page ok but gives error after clicking submit - what I am expecting is spring to fill in the user roles and then go to main.jsp.
spring main config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- ############################################# -->
<context:component-scan base-package="frostbyte.igloo" />
<!-- ############################################# -->
<mvc:resources mapping="/resources/**" location="/resources/"/>
<!-- ############################################# -->
<mvc:annotation-driven/>
<!-- ############################################# -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- ############################################# -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"></property>
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
<!-- ############################################# -->
</beans>
spring security config:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- ############################################# -->
<beans:bean id="FrostByteAuthenticationProvider" class="frostbyte.igloo.jsp.custom.FrostByteAuthenticationProvider"></beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="FrostByteAuthenticationProvider"></authentication-provider>
</authentication-manager>
<!-- ############################################# -->
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/login"
login-page="/login"
default-target-url="/main"
username-parameter="j_username"
password-parameter="j_password"
authentication-failure-url="/login?auth=fail"/>
<intercept-url pattern="/login" access="permitAll"></intercept-url>
<intercept-url pattern="/logout" access="permitAll"></intercept-url>
<intercept-url pattern="/**" access="hasRole('ADMIN')"/>
<logout logout-url="/logout" logout-success-url="/logout_success"></logout>
</http>
<!-- ############################################# -->
</beans:beans>
the AuthenticationProvider (non of these log messages ever get printed) :
package frostbyte.igloo.jsp.custom;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import frostbyte.common.FrostbyteRole;
import frostbyte.common.FrostbyteUser;
public class FrostByteAuthenticationProvider implements AuthenticationProvider
{
private static final Logger LOG = Logger.getLogger(FrostByteAuthenticationProvider.class);
#Override
public boolean supports(Class<?> authentication)
{
LOG.error("FrostByteAuthenticationProvider : supports : Marker 1");
System.out.println("FrostByteAuthenticationProvider : supports : Marker 1");
return true;
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
LOG.error("FrostByteAuthenticationProvider : authenticate : Marker 1");
System.out.println("FrostByteAuthenticationProvider : authenticate : Marker 1");
Authentication rtn = null;
String username = authentication.getName();
String password = authentication.getCredentials().toString();
LOG.error("FrostByteAuthenticationProvider : authenticate : Marker 10 : username = "+username);
LOG.error("FrostByteAuthenticationProvider : authenticate : Marker 20 : password = "+password);
FrostbyteUser user = new FrostbyteUser(); //for test everything validates
user.setUsername(username);
user.getRoles().add(new FrostbyteRole("ADMIN"));
LOG.debug("Authenticate : Marker 100");
//if (user.getUsername().equalsIgnoreCase("username"))
if (true)
{
LOG.debug("Authenticate : Marker 200");
if (true)
//if (password.equalsIgnoreCase(user.getPassword()))
{
LOG.debug("Authenticate : Marker 300");
List<GrantedAuthority> grants = new ArrayList<GrantedAuthority>();
for (FrostbyteRole _role:user.getRoles())
{
if (_role.equals("ADMIN"))
{
for ( String __role : _role.getRoles() )
{
grants.add(new SimpleGrantedAuthority(__role.toUpperCase()));
}
}
}
rtn = new UsernamePasswordAuthenticationToken(username, password, grants);
LOG.debug("Authenticate : Marker 898,000 : rtn = "+ rtn);
}
LOG.debug("Authenticate : Marker 899,000 : rtn = "+ rtn);
}
LOG.debug("Authenticate : Marker 900,000 : rtn = "+ rtn);
return rtn;
}
}
the login jsp:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# include file="/WEB-INF/jsp/include.jsp" %>
<meta http-equiv="pragma" content="no-cache">
<html>
<head>
<title></title>
<link rel="stylesheet" href="resources/styles.css" type="text/css" media="screen" />
<style type="text/css"></style>
</head>
<body>
request.getAttribute("message") = <%= request.getAttribute("message") %>
<br />
request.getParameter("message") = <%= request.getParameter("message") %>
<form action="<c:url value = "/j_spring_security_check" />" method="post">
<br /><br /><br />
<br /><br /><br />
<br />
<div class="containerCenterAlign">
<div class="container">
<div class="titleClass">Igloo<br /><div class="errorMessage"><%= message %></div></div>
<ul class="loginUL">
<li class="loginLeft">
<label class="loginLabel" for="j_username">Username</label>
<input id="username" name="j_username" class="loginText" type="text" value="" maxlength="150" />
<label class="loginLabel" for="j_password">Password</label>
<input id="password" name="j_password" class="loginText" type="password" value="" maxlength="150" />
</li>
<li class="loginRight">
<input type="submit" name="submit" id="submit" value="Login" class="loginSubmit" />
</li>
</ul>
<div style="clear: both; height: 2px;"></div>
</div>
</div>
</form>
</body>
</html>
include.jsp:
<%# page language="java" contentType="text/html;charset=UTF-8"%>
<%# page session="false"%>
<%# page import="java.io.*" %>
<%# page import="java.util.*" %>
<%# page import="frostbyte.*" %>
<%# page import="org.apache.log4j.*" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="s" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="sform" uri="http://www.springframework.org/tags/form"%>
<%# taglib prefix="frostbyte" uri="http://frostbyte/tags" %>
I managed to stumble across the fix by removing
login-processing-url="/login"
I am posting these results here since its almost impossible to find good spring tutorials, even in the 4 spring books I have. Note I also had to add filter for the resources

Resources