You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Glassfish7多WAR应用SSO配置异常:登录后重定向回Login.war

GlassFish7跨WAR包SSO登录后重定向回登录页的原因与解决办法

核心问题分析

1. 容器认证与自定义登录逻辑冲突

Login.war的web.xml配置了FORM类型的容器认证,但LoginController里又自行实现了用户名密码校验、手动往session存入用户信息的逻辑。这导致容器安全上下文未完成认证流程,Start.war通过getUserPrincipal()检查时,容器认为用户未认证,直接重定向回登录页。

2. Login.war未触发容器认证流程

Login.war的web.xml仅配置了<login-config>,但没有添加<security-constraint>。容器只有在访问受保护资源时才会触发认证,Login.war没有受保护资源,容器不会初始化认证会话,自定义登录的session属性无法被容器的安全机制识别。

3. Start.war登录页路径配置错误

Start.war中<form-login-page>配置为/login/login.xhtml,但Login.war的上下文根是Login,正确路径应为/Login/login.xhtml,否则容器无法找到登录页(不过这不是导致重定向回Login的核心原因,但会引发其他异常)。

4. 自定义重定向未利用容器认证跳转机制

FORM认证模式下,容器会自动处理登录成功后的跳转逻辑(跳转到用户最初请求的受保护页面),而手动调用redirect()会跳过容器的认证会话同步,导致Start.war无法识别已认证状态。


解决方案

方案一:完全使用容器FORM认证(推荐)

1. 调整Login.war的web.xml

移除自定义登录逻辑依赖,确保容器能正确处理认证:

<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    <display-name>Login</display-name>
    <welcome-file-list>
        <welcome-file>login.xhtml</welcome-file>
    </welcome-file-list>

    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>jdbcRealm</realm-name>
        <form-login-config>
            <form-login-page>/login.xhtml</form-login-page>
            <form-error-page>/login-error.xhtml</form-error-page>
        </form-login-config>
    </login-config>

    <!-- 保留其他配置,如Faces Servlet、session-config等 -->
</web-app>

2. 修改Login.xhtml的表单

使用容器认证的标准表单参数,action必须为j_security_check:

<h:form id="loginForm" action="j_security_check">
    <h:inputText id="username" name="j_username" value="#{loginController.username}" />
    <h:inputSecret id="password" name="j_password" value="#{loginController.password}" />
    <h:commandButton value="Login" type="submit" />
</h:form>

3. 简化LoginController

移除自定义校验逻辑,仅保留属性 getter/setter:

package login.web;

import java.io.Serializable;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;

@RequestScoped
@Named
public class LoginController implements Serializable {
    private static final long serialVersionUID = -5346634778960677989L;

    private String username;
    private String password;

    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; }
}

4. 修正Start.war的登录页路径

<form-login-config>
    <form-login-page>/Login/login.xhtml</form-login-page>
    <form-error-page>/Login/login-error.xhtml</form-error-page>
</form-login-config>

5. 开启GlassFish跨应用SSO

在domain.xml中确保开启单签:

<glassfish-web-app>
    <single-sign-on enabled="true" />
</glassfish-web-app>

或通过GlassFish管理控制台,在配置的HTTP服务中开启SSO。


方案二:保留自定义登录,同步容器安全上下文

如果必须保留自定义校验逻辑,需在登录成功后手动触发容器认证:

public void login() {
    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext externalContext = context.getExternalContext();
    User user = loginService.findUserByUsername(username);

    if (user != null && user.getPassword().equals(SHA256Util.hashPassword(password))) {
        try {
            // 触发容器认证,同步安全上下文
            externalContext.login(username, password);
            context.getExternalContext().getSessionMap().put("user", user);
            externalContext.redirect(URL + "/Start");
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid username or password", null));
    }
}

同时确保Login.war和Start.war的session cookie路径均为/(已在配置中设置),且GlassFish开启跨应用SSO。


内容的提问来源于stack exchange,提问作者herohannes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:35:54