我有一个安装了spring security的JSF项目,我使用forward方法进行登录。但我无法将页面重定向到AuthenticationBean.java中的secured.xhtml。似乎“forward()”方法导致了这一点。但是身份验证成功完成,我无法重定向页面。 如果没有forward方法,我可以成功重定向页面。那么,帮忙吗?
的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>
答案 0 :(得分:0)
在JSF中,当您在操作方法上返回String时,它默认触发转发而不是重定向(除非您在faces-config.xml
上配置了导航规则并在其上放置了<redirect />
)。
在你的情况下,你可以从ExternalContext中调用redirect()
而不是返回一个String:
在你的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。