I am working with Spring Security & JSF . When ever login is submitted , page is getting reloaded nothing happens, action="${pageContext.request.contextPath}/j_spring_security_check" is not getting called.
Please help. Thank You in advance.
Below are my pages and configuration's:
login.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:cls="http://emia.com/emia/ui"
xmlns:cat360="http://java.sun.com/jsf/composite/components">
<ui:composition template="/templates/login/loginTemplate.xhtml">
<ui:define name="body">
<h:outputStylesheet>
.panelGridValign td { vertical-align: top !important; }
.rf-p-hdr{
height: 15 px !important;
display: block !important;
border: none !important;
background: url("${facesContext.externalContext.requestContextPath}/images/menuBg.jpg") repeat-x 0 0 !important;
padding:5px 5px 5px 5px !important;
color : #ffffff !important
}
.topalgn {
vertical-align: top;
}
#menu-nav {
background: #fff url("${facesContext.externalContext.requestContextPath}/images/menuBg.jpg") repeat-x 0 0;
height: 30px;
padding: 0;
display: block;
border: none
}
.content {
padding: 0px !important;
min-height: 0px !important;
}
</h:outputStylesheet>
<f:event listener="#{loginBean.updateMessages}" type="preRenderView" />
<div class="contentBg">
<div id="menu-nav"></div>
<div class="wrapper">
<div class="content">
<div class="logInSection">
<div class="leftBlock">
<h2>Welcome to Nomad</h2>
<h:graphicImage library="images" url="#{loginBean.loginPageImage}"/>
<div class="rightBlock">
<h3>Login</h3>
<div class="rightLoginBlock">
<h:form id="loginForm" prependId="false"
action="${pageContext.request.contextPath}/j_spring_security_check">
<table cellpadding="0" cellspacing="0" width="99%">
<tbody>
<tr>
<td class="labelClass1">User Name</td>
<td class="fieldClass"><h:inputText id="j_username"
required="true" requiredMessage="Username is mandatory"
style=" width :150px;">
</h:inputText></td>
</tr>
<tr>
<td class="labelClass1">Password</td>
<td class="fieldClass"><h:inputSecret id="j_password"
required="true" requiredMessage="Password is mandatory"
styleClass="form_input" style=" width :150px;">
</h:inputSecret></td>
</tr>
<tr>
<td class="labelClass1">Company</td>
<td class="fieldClass"><h:selectOneMenu
id="loginCompany" value="#{loginBean.selectedCompany}"
disabled="#{!loginBean.multiHosted}" required="true"
requiredMessage="Company is mandatory"
styleClass="form_select" style=" width :50px;">
<f:selectItems value="#{loginBean.companyCodeList}"></f:selectItems>
<f:ajax listener="#{loginBean.companySelected}"
render="loginSite" event="change" execute="#this" />
</h:selectOneMenu> <h:inputHidden value="#{loginBean.selectedCompany}"
id="loginCompanyHidden" /></td>
</tr>
<tr>
<td class="labelClass1">Site</td>
<td class="fieldClass"><h:selectOneMenu id="loginSite"
value="#{loginBean.selectedSite}" required="true"
requiredMessage="Site is mandatory"
styleClass="form_select" style=" width :50px;">
<f:selectItems value="#{loginBean.siteCodeList}"></f:selectItems>
</h:selectOneMenu></td>
</tr>
<tr>
<td class="labelClass1"></td>
<td align="right" class="fieldClass"><span
style="text-align: right; float: right;"> <h:commandButton
type="submit" id="login"
onclick="loginTest(); return false;" value="login"
styleClass="submitButton" /> <br /> <br />
<a4j:commandLink
styleClass="forgetPass" value="Forgot Password?">
<rich:componentControl target="forgotPasswordPopup"
operation="show" event="click" />
</a4j:commandLink>
</span></td>
</tr>
<tr>
<td colspan="2" class="labelClass1"><a4j:outputPanel
id="loginErrorOutPanel" ajaxRendered="true"
styleClass="error" width="250px">
<h:panelGrid id="loginErrorPanel" width="250px">
<h:messages errorClass="error" infoClass="info" />
</h:panelGrid>
</a4j:outputPanel></td>
</tr>
</tbody>
</table>
</h:form>
</div>
<div class="shadow"></div>
</div>
</div>
</div>
</div>
</div>
<a4j:jsFunction name="clearSessionContext"
action="#{loginBean.clearSessionContext}">
</a4j:jsFunction>
<a4j:jsFunction name="loginTest" action="#{loginBean.validateLogin}"
oncomplete="submitForm(); return false;"
render="loginErrorOutPanel,loginErrorPanel">
</a4j:jsFunction>
<script>
// To focus on page startup
jQuery(document).ready(function(){
clearSessionContext();
jQuery("#j_username").focus();
});
// Submitting the form on press enter
jQuery(document).ready(jQuery('html').bind('keypress', function(e)
{
if(e.keyCode == 13)
{
clearSessionContext();
loginTest();
//submitForm();
}
}));
// does the validation and submits the form
function submitForm() {
var validationMsg = '';
if(jQuery("#j_username").val().length == 0) {
validationMsg = "Please enter the User Name";
}
if(jQuery("#j_password").val().length == 0) {
validationMsg += "\nPlease enter the Password";
}
if(jQuery("#loginCompany").val().length == 0) {
validationMsg += "\nPlease enter the Company";
}
if(jQuery("#loginSite").val().length == 0) {
validationMsg += "\nPlease enter the Site";
}
if (validationMsg.length == 0) {
document.loginForm.action = "${facesContext.externalContext.requestContextPath}/j_spring_security_check";
document.loginForm.submit();
}
}
function resetForm() {
document.loginFormId.reset();
}
</script>
</ui:define>
</ui:composition>
</ui:composition>
sso-context.xml:
<?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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<!-- TODO: Import META-INF/spring/spring-security-mandatory.xml. Copy this
entry from the solution -->
<beans:import resource="web-security-context.xml" />
<http pattern="/login/**" security="none" />
<http pattern="/pages/login/**" security="none" />
<http pattern="/css/**" security="none" />
<http pattern="/images/**" security="none" />
<http pattern="/rfRes/**" security="none" />
<http pattern="/resources/**" security="none" />
<http pattern="/javax.faces.resource/**" security="none" />
<http pattern="/js/*" security="none" />
<http pattern="/pages/login/login.jsf" security="none" />
<http pattern="/logout.xhtml" security="none" />
<!-- <http pattern="/newlogin.jsp" security="none" /> -->
<http pattern="/logout.jsp" security="none" />
<http pattern="/error.jsp" security="none" />
<http pattern="/favicon.ico" security="none" />
<!-- <http pattern="/templates/**" security="none" /> -->
<!-- <http pattern="/index.html" security="none" /> <http pattern="/index.xhtml"
security="none" /> -->
<http use-expressions="false" auto-config="false" entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/j_spring_security_check"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/j_spring_security_logout"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/pages/login/login.jsf" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/help/**" access="IS_AUTHENTICATED_FULLY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<!-- <custom-filter ref="hdivValidationFilter" before="SECURITY_CONTEXT_FILTER" /> -->
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<custom-filter ref="basicAuthenticationFilter" after="BASIC_AUTH_FILTER" />
<custom-filter ref="applicationSessionFilter" before="FORM_LOGIN_FILTER" />
<custom-filter ref="applicationUsernamePasswordAuthProcessingFilter"
position="FORM_LOGIN_FILTER" />
<logout logout-url="/j_spring_security_logout"
invalidate-session="true" success-handler-ref="logoutSuccessHandler" />
</http>
<!-- <beans:bean id="hdivValidationFilter"
class="org.hdiv.filter.ValidatorFilter">
</beans:bean> -->
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:constructor-arg name="loginFormUrl" value="/pages/login/login.jsf" />
</beans:bean>
<beans:bean id="sessionManagementFilter"
class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository"
ref="httpSessionSecurityContextRepository" />
<!-- this permits redirection to session timeout page from javascript/ajax
or http -->
<beans:property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
</beans:bean>
<beans:bean id="jsfRedirectStrategy"
class=".admin.security.JsfSessionTimeoutStrategy">
<beans:constructor-arg name="invalidSessionUrl"
value="/pages/login/login.jsf" />
</beans:bean>
<beans:bean id="httpSessionSecurityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
<beans:bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<beans:constructor-arg name="authenticationManager" ref="authenticationManager" />
<beans:constructor-arg name="authenticationEntryPoint" ref="authenticationEntryPoint" />
</beans:bean>
<beans:bean id="applicationUsernamePasswordAuthProcessingFilter"
class=".admin.security.applicationUserNamePasswordFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
<beans:property name="authenticationSuccessHandler"
ref="defauthenticationSuccessHandler" />
<beans:property name="authenticationFailureHandler"
ref="defauthenticationFailureHandler" />
</beans:bean>
<beans:bean id="defauthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"
p:alwaysUseDefaultTargetUrl="false" p:defaultTargetUrl="/index.jsp" />
<!-- <beans:bean id="defauthenticationSuccessHandler" class=".admin.security.applicationAuthenticationSuccessHandler"
p:alwaysUseDefaultTargetUrl="false" > <beans:property name="defaultTargetUrl"
value="/index.jsp" /> </beans:bean> -->
<!-- <beans:bean id="defauthenticationFailureHandler" class=".admin.security.applicationAuthenticationFailureHandler"
p:defaultFailureUrl="/newlogin.jsp?login_error=1"> <beans:property name="redirectPage"
value="/newlogin.jsp" /> <beans:property name="contextRelative" value="true"
/> </beans:bean> -->
<beans:bean id="defauthenticationFailureHandler"
class=".admin.security.applicationAuthenticationFailureHandler"
p:defaultFailureUrl="/pages/login/login.jsf?login_error=1">
</beans:bean>
<authentication-manager alias="authenticationManager">
<!-- <authentication-provider ref="cmsAuthenticationProvider" /> -->
<authentication-provider user-service-ref="applicationLoginService" /> <!-- for form-login -->
<!-- <authentication-provider ref="kerberosServiceAuthenticationProvider"
/> -->
<authentication-provider ref="rememberMeAuthenticationProvider" />
</authentication-manager>
<!-- This ensures that remember-me is added as an authentication provider -->
<!-- <beans:bean id="rememberMeAuthenticationProvider" class=".admin.security.applicationAuthenticationProvider">
</beans:bean> -->
<beans:bean id="rememberMeAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="applicationLoginService" />
</beans:bean>
<beans:bean id="logoutSuccessHandler"
class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
<beans:property name="defaultTargetUrl" value="/pages/login/login.jsf?login_error=2" />
</beans:bean>
<beans:bean class=".admin.security.applicationSessionFilter"
id="applicationSessionFilter">
<beans:constructor-arg name="securityContextRepository"
ref="httpSessionSecurityContextRepository" />
<beans:constructor-arg name="invalidSessionStrategy"
ref="jsfRedirectStrategy" />
</beans:bean>
</beans:beans>
LoginBean.java:
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.model.SelectItem;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.web.WebAttributes;
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private Logger LOGGER = LoggerFactory.getLogger(getClass());
private String username = "";
private String password = "";
private String company = "";
private String login;
public String login() {
try {
LOGGER.debug("Login initiated....");
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
if (validateLoginRequest(request)) {
RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())
.getRequestDispatcher("/j_spring_security_check");
dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
FacesContext.getCurrentInstance().responseComplete();
}
}
catch (Exception ex) {
CommonUtil.addFacesMessage("Login Failed . Bad Credentials", FacesMessage.SEVERITY_ERROR);
}
return null;
}
public boolean validateLogin() {
LOGGER.debug("Login initiated....");
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
if (validateLoginRequest(request)) {
return true;
}
else {
return false;
}
}
public void clearSessionContext() {
LOGGER.debug("Clearing.....SessionContext.....");
if (SecurityContextHolder.getContext() != null) {
SecurityContextHolder.createEmptyContext();
SecurityContextHolder.getContext().setAuthentication(null);
((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession(true);
}
}
private boolean validateLoginRequest(HttpServletRequest request) {
clearExceptions();
String userName = request.getParameter("j_username");
String password = request.getParameter("j_password");
String company = request.getParameter("loginCompany");
String site = request.getParameter("loginSite");
if (userName == null || (userName != null && userName.isEmpty())) {
CommonUtil.addFacesMessage("Username is mandatory", FacesMessage.SEVERITY_ERROR);
return false;
}
if (password == null || (password != null && password.isEmpty())) {
CommonUtil.addFacesMessage("Password is mandatory", FacesMessage.SEVERITY_ERROR);
return false;
}
if (serverConfigService.getServerHostingType().equalsIgnoreCase(ServerHostingType.MULTIHOSTING.toString())) {
if (company == null || (company != null && company.isEmpty())) {
CommonUtil.addFacesMessage("Company is mandatory", FacesMessage.SEVERITY_ERROR);
return false;
}
}
if (site == null || (site != null && site.isEmpty())) {
CommonUtil.addFacesMessage("Site is mandatory", FacesMessage.SEVERITY_ERROR);
return false;
}
return true;
}
}
Related
I am trying to use spring security with two login page and configure two different http section in my spring-security.xml I also have two authentication-manager which handles authentication using custom UserDetailsService.
Below are my code snippets
spring-security.xml
<!-- http Section for Admins -->
<http auto-config="true" use-expressions="true" authentication-manager-ref="adminAuth" pattern="/admin/**">
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login login-page="/adminLogin" default-target-url="/admin/home" authentication-failure-url="/views/homePages/adminHome" username-parameter="username"
password-parameter="password"
login-processing-url="/authenticateAdmin" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf disabled="true"/>
</http>
<authentication-manager id="adminAuth" alias="adminAuth">
<authentication-provider user-service-ref='adminAuthService'>
<password-encoder hash="md5" />
</authentication-provider>
</authentication-manager>
<beans:bean id="adminAuthService" class="security.AdminAuth">
</beans:bean>
<!-- http Section for Students -->
<http auto-config="true" use-expressions="true" authentication-manager-ref="studentAuth" pattern="/student/**" >
<intercept-url pattern="/**" access="hasRole('ROLE_STUDENT')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login login-page="/studentLogin" default-target-url="/student/home" authentication-failure-url="/studentLogin" login-processing-url="/authenticateStudent" />
<logout logout-success-url="/studentLogin" />
<!-- enable csrf protection -->
<csrf disabled="true"/>
</http>
<authentication-manager id="studentAuth" alias="studentAuth">
<authentication-provider user-service-ref='studentAuthService'>
<password-encoder hash="md5" />
</authentication-provider>
</authentication-manager>
<beans:bean id="studentAuthService" class="security.StudentAuth">
</beans:bean>
UserDetailService implementor class
package security;
#Service
public class AdminAuth implements UserDetailsService {
#Autowired
AdminService adminService;
public UserDetails loadUserByUsername(String authAttribute) throws UsernameNotFoundException {
Admin admin = getAdminByUname(authAttribute);
List<SimpleGrantedAuthority> authList = new ArrayList();
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
User user = new User(authAttribute, admin.getPassword(), authList);
return user;
}
private Admin getAdminByUname(String authAttribute) {
Admin admin = adminService.getAdminbyUname(authAttribute);
return admin;
}
}
Admin login page
<h2 class="text-center">Staff Login</h2>
<form class="login-form" action="/authenticateAdmin" method="POST">
<div class="form-group">
<label for="exampleInputEmail1" class="text-uppercase">Username</label> <input type="text" class="form-control" placeholder="Email or Mobile" id="username">
</div>
<div class="form-group">
<label for="exampleInputPassword1" class="text-uppercase">Password</label> <input type="password" class="form-control" placeholder="" id="password">
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox" class="form-check-input"> <small>Remember Me</small>
</label>
<button type="submit" class="btn btn-login float-right">Submit</button>
</div>
</form>
Now when I open login page enter username/password and hit login then my loadUserByUsername is not getting invoked.
What I doing wrong here.
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>
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.
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
I have trouble in spring security 3.1.
I'm going to use spring security openid-login with gmail, and I want to get user information using attribute-exchange. but if I use it, it is always called when user log-in my website.
How can i call only once at user sign-in my website?
I managed sign-in at openIdAuthFailureHandler, and I want to get user information in this bean...please help me!
(I found security:remember-me, but it doesn't work..)
security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:global-method-security
secured-annotations="enabled" proxy-target-class="true" />
<security:http auto-config="true" access-denied-page="/denied/accessDenied">
<security:intercept-url pattern="/admin/**"
access="ROLE_ADMIN" />
<security:intercept-url pattern="/reservation/**"
access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/board/**"
access="ROLE_ADMIN, ROLE_USER" />
<security:openid-login login-page="/"
login-processing-url="/j_spring_openid_security_check.do"
authentication-success-handler-ref="customAuthenticationHandler"
authentication-failure-handler-ref="openIdAuthFailureHandler">
<security:attribute-exchange identifier-match="https://www.google.com/.*" >
<security:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" />
<security:openid-attribute name="firstname" type="http://axschema.org/namePerson/first" required="true" />
</security:attribute-exchange>
</security:openid-login>
<security:logout logout-url="/j_spring_openid_security_logout.do"
logout-success-url="/" invalidate-session="true" />
<!-- <security:http-basic /> -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<!-- <security:user-service properties="/WEB-INF/resources/users.xml"
/> -->
<security:password-encoder ref="passwordEncoder" />
<security:jdbc-user-service id="userDetailsService"
data-source-ref="dataSource"
users-by-username-query="SELECT id as id, passwd as passwd, 1 as enabled FROM user WHERE id=?"
authorities-by-username-query="SELECT id as id, power as authority FROM user WHERE id=?" />
<!-- <security:password-encoder hash="sha-256"></security:password-encoder> -->
</security:authentication-provider>
</security:authentication-manager>
<bean id="customTokenRepository" class="com.jinyoung.reservation.openid.CustomTokenRepository" />
<bean id="openIdAuthFailureHandler" class="com.jinyoung.reservation.openid.OpenIDAuthenticationFailureHandler"/>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
</beans>
OpenIDAuthenticationFailureHandler
public class OpenIDAuthenticationFailureHandler extends
SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (exception instanceof UsernameNotFoundException && exception.getAuthentication() instanceof OpenIDAuthenticationToken && ((OpenIDAuthenticationToken) exception.getAuthentication()).getStatus().equals(OpenIDAuthenticationStatus.SUCCESS)) {
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
request.getSession(true).setAttribute("USER_OPENID_CREDENTIAL", ((UsernameNotFoundException)exception).getExtraInformation());
OpenIDAuthenticationToken openIdAuth = (OpenIDAuthenticationToken)exception.getAuthentication();
request.getSession(true).setAttribute("USER_OPENID_CREDENTIAL_EXTRA", openIdAuth);
for(OpenIDAttribute attr : openIdAuth.getAttributes()) {
System.out.printf("AX Attribute: %s, Type: %s, Count: %d\n", attr.getName(), attr.getType(), attr.getCount());
for(String value : attr.getValues()) {
System.out.printf(" Value: %s\n", value);
}
}
redirectStrategy.sendRedirect(request, response, "/login/registrationOpenid");
// redirect to create account page
/*redirectStrategy.sendRedirect(request, response,
"/?fail=true");*/
} else {
super.onAuthenticationFailure(request, response, exception);
}
}
}
Ran in to a similar problem which I solved by having two different form targets (j_spring_openid_security_check_signup and j_spring_openid_security_check) for the signup/login page. One used when signing up and one when logging in. In spring-security.xml we use two different configs, one that asks for attributes and one that don't:
<!-- Configure attribute-exchange for signup -->
<!-- will only match /j_spring_openid_security_check_signup -->
<security:http auto-config="true" use-expressions="true" path-type="ant" pattern="/j_spring_openid_security_check_signup">
<security:openid-login
login-processing-url="/j_spring_openid_security_check_signup"
user-service-ref="userDetailsService"
authentication-failure-handler-ref="authenticationFailureHandler"
authentication-success-handler-ref="authenticationSuccessHandler">
<security:attribute-exchange identifier-match="https://www.google.com/.*" >
<security:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" />
<security:openid-attribute name="firstname" type="http://axschema.org/namePerson/first" required="true" />
</security:attribute-exchange>
</security:openid-login>
</security:http>
<!-- Skip attribute-exchange at log-in -->
<!-- match everything else -->
<security:http auto-config="true" use-expressions="true" path-type="ant">
<security:openid-login
login-processing-url="/j_spring_openid_security_check"
user-service-ref="userDetailsService"
authentication-failure-handler-ref="authenticationFailureHandler"
authentication-success-handler-ref="authenticationSuccessHandler"
/>
</security:http>
Then in the authenticationSuccessHandler you will have access to attributes while signing in but not at log-in.
-------------------------------I solved!!!------------------------------------------
I modified spring-security-openid-3.1.1.RELEASE.jar, and I call attribute-change only once at user access my site first time. if one who want to know, give me e-mail kjy30532#gmail.com !