2012-08-16 318 views
0

我有一个安装了spring security的JSF项目,我使用forward方法来进行登录。但是我无法将页面重定向到AuthenticationBean.java中的secured.xhtml。看起来像“forward()”方法造成这种情况。但身份验证成功完成,我无法重定向页面。 没有转发方法,我可以成功重定向页面。那么,帮忙?Spring Security在身份验证后无法重定向页面

的web.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 
    <context-param> 
     <param-name>javax.faces.PROJECT_STAGE</param-name> 
     <param-value>Development</param-value> 
    </context-param> 

    <servlet> 
     <servlet-name>Faces Servlet</servlet-name> 
     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>Faces Servlet</servlet-name> 
     <url-pattern>*.xhtml</url-pattern> 
    </servlet-mapping> 

    <session-config> 
     <session-timeout> 
      30 
     </session-timeout> 
    </session-config> 

    <welcome-file-list> 
     <welcome-file>index.xhtml</welcome-file> 
    </welcome-file-list> 

    <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> 
     <dispatcher>REQUEST</dispatcher> 
     <dispatcher>FORWARD</dispatcher> 
    </filter-mapping> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/spring-security.xml 
     </param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
</web-app> 

弹簧security.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-3.0.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

<security:http auto-config="true" use-expressions="true" access-denied-page="/denied.xhtml"> 

    <security:intercept-url pattern="/login.xhtml" access="permitAll"/> 
    <security:intercept-url pattern="/secured.xhtml" access="hasRole('ROLE_ADMIN')"/> 

    <security:form-login 
    login-page="/login.xhtml" 
    authentication-failure-url="/login.xhtml?error=true" 
    default-target-url="/"/> 

    <security:logout 
    invalidate-session="true" 
    logout-success-url="/index.xhtml" 
    logout-url="/logout.xhtml"/> 

</security:http> 

<security:authentication-manager> 
    <security:authentication-provider user-service-ref="customUserDetailsService"> 
    <security:password-encoder ref="passwordEncoder"/> 
    </security:authentication-provider> 
</security:authentication-manager> 

<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> 

    <bean id="customUserDetailsService" class="com.triune.services.CustomUserDetailsService"/> 

</beans> 

CustomUserDetailService.java(这是从来没有所谓的)

package com.triune.services; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 

import com.triune.dao.UserDAO; 
import com.triune.entities.LoginCredential; 
import org.springframework.dao.DataAccessException; 
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.transaction.annotation.Transactional; 

@Transactional(readOnly = true) 
public class CustomUserDetailsService implements UserDetailsService { 

    private UserDAO userDAO = new UserDAO(); 
    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException 
    { 
     UserDetails user = null; 

     try 
     { 
      LoginCredential dbUser = userDAO.searchDatabase(username); 

      user = new User(
       dbUser.getUsername(), 
       dbUser.getPassword().toLowerCase(), 
       true, 
       true, 
       true, 
       true, 
       getAuthorities(dbUser.getAccess()) 
      ); 
     } 
     catch (Exception e) 
     { 
      throw new UsernameNotFoundException("Error in retrieving user"); 
     }  
     return user; 
    } 

    public Collection<GrantedAuthority> getAuthorities(Integer access) 
    { 
     List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2); 

     authList.add(new SimpleGrantedAuthority("ROLE_USER")); 

     if (access.compareTo(1) == 0) 
     { 
      authList.add(new SimpleGrantedAuthority("ROLE_ADMIN")); 
     } 

     return authList; 
    } 
} 

AuthenticationBean.java(这被称为通过登录页面)

package com.triune.beans; 

import java.io.IOException; 
import java.io.Serializable; 
import javax.enterprise.context.SessionScoped; 
import javax.faces.context.ExternalContext; 
import javax.faces.context.FacesContext; 
import javax.inject.Named; 
import javax.servlet.RequestDispatcher; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 

@Named("authenticationBean") 
@SessionScoped 
public class AuthenticationBean implements Serializable 
{ 
    public String doLogin() throws IOException, ServletException 
    { 
     ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); 
     RequestDispatcher dispatcher = ((ServletRequest)context.getRequest()).getRequestDispatcher("j_spring_security_check"); 
     dispatcher.forward((ServletRequest)context.getRequest(), (ServletResponse)context.getResponse()); 
     FacesContext.getCurrentInstance().responseComplete(); 
     return "secured.xhtml"; 
    } 

    public String doLogout() 
    { 
     FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); 
     return "index.xhtml"; 
    } 
} 

login.xhtml(简单的登录页面)

<?xml version='1.0' encoding='UTF-8' ?> 
<!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:p="http://primefaces.org/ui"> 
    <h:head> 
     <title>Login Page</title> 
    </h:head> 
    <h:body> 
     <h1>Login Please</h1> 
     <p>This is a really simple login page.</p> 
     <h:form id="loginForm" prependId="false"> 
      <h:panelGroup> 
       Username : <p:inputText id="j_username" required="true"/> 
      </h:panelGroup> 
      <br/> 
      <h:panelGroup> 
       Password : <p:inputText id="j_password" required="true"/> 
      </h:panelGroup> 
      <br/><br/> 
      <h:panelGroup> 
       <p:commandButton type="submit" id="login" action="#{authenticationBean.doLogin()}" value="login"/> 
      </h:panelGroup> 
     </h:form> 
    </h:body> 
</html> 
+1

您可以使用html

标记并将其发布到j_spring_security_check,并使用default-target-url属性指向secured.xhtml。如果你想使用JSF''标签,然后看看这个答案http://stackoverflow.com/questions/11742283/spring-custom-jsf-login-page-always-bad-credentials/ – Ravi 2012-08-17 03:25:54

回答

0

在JSF中,当你的操作方法返回一个字符串,它在默认情况下会触发一个前锋,而不是重定向(除非你配置的导航规则在faces-config.xml上并放上<redirect />就可以了)。

在你的情况,而不是返回一个字符串,你可以只调用redirect()距离的ExternalContext:

在utils的类把这样的方法(或让自己OmniFaces):

public static void redirect(String url) throws IOException { 
    ExternalContext ctx = FacesContext.getCurrentInstance() 
     .getExternalContext(); 
    if (url.startsWith("http://") || url.startsWith("https://") 
      || url.startsWith("/")) { 
     ctx.redirect(url); 
    } else { 
     ctx.redirect(ctx.getRequestContextPath() + "/" + url); 
    } 
} 

和改变你的方法doLogin()

public void doLogin() throws IOException, ServletException 
{ 
    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); 
    RequestDispatcher dispatcher = ((ServletRequest)context.getRequest()).getRequestDispatcher("j_spring_security_check"); 
    dispatcher.forward((ServletRequest)context.getRequest(), (ServletResponse)context.getResponse()); 
    FacesContext.getCurrentInstance().responseComplete(); 
    redirect("secured.xhtml"); 
} 

另请参见this answer