java - 我无法重新登录 JSF 页面,除非关闭浏览器或重新启动 Glassfish

标签 java glassfish

index.xhtml是我的登录页面

我在 Glassfish 中使用 SHA-256 作为加密算法创建了一个 Realm

Session.java 是登录 bean,包含:

package beans;


import java.security.MessageDigest;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author bk-laptop
 */
@ManagedBean(name = "mngsession")
@SessionScoped
public class Session {

    private String userid;
    private String password;

    /**
     * Creates a new instance of Session
     */
    public Session() {
    }

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String login() throws ServletException {

        if (this.userid.isEmpty()) {
            FacesMessage message = new FacesMessage("Please enter a user !!!");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);

            FacesContext.getCurrentInstance().addMessage("form-login:usernameInput", message);

            return null;
        }

        if (this.password.isEmpty()){
             FacesMessage message = new FacesMessage("Please enter a password !!!");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            FacesContext.getCurrentInstance().addMessage("form-login:usernameInput", message);
            return null;
        }

        //context.addMessage(null,new FacesMessage("Ok"));
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        try {


            request.login(this.userid, this.password);
        } catch (ServletException e) {

            FacesMessage message = new FacesMessage("Login Failed !!!");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);

            FacesContext.getCurrentInstance().addMessage("form-login:usernameInput", message);

            return null;
        }

        return "/products/List";

    }

    public void logout() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        try {
            request.logout();

        } catch (ServletException e) {

        }

    }

    private String sha256(String base) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(base.getBytes("UTF-8"));
            StringBuffer hexString = new StringBuffer();

            for (int i = 0; i < hash.length; i++) {
                String hex = Integer.toHexString(0xff & hash[i]);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception ex) {
            throw new RuntimeException(ex);

        }
    }


}

当我第一次登录时,我可以转到/products/List 并且登录成功,但是当我注销并重新登录时,登录失败...请帮助...

这是索引的代码:

<form   id="form-login" method="POST" action="j_security_check">
            <div style="text-align: center;" >
                <div style="box-sizing: border-box; display: inline-block; width: auto; max-width: 480px; background-color: #FFFFFF; border: 2px solid #0361A8; border-radius: 5px; box-shadow: 0px 0px 8px #0361A8; margin: 50px auto auto;">
                    <div style="background: #0361A8; border-radius: 5px 5px 0px 0px; padding: 15px;">
                        <span style="font-family: verdana,arial; color: #D4D4D4; font-size: 1.00em; font-weight:bold;">Enter your login and password</span></div></div></div>
            <div style="background: ; padding: 15px">


           <p><strong>Please type your user name: </strong>
                <input type="text" name="j_username" size="25" /></p>
            <p><strong>Please type your password: </strong>
                <input type="password" size="15" name="j_password" /></p>
            <p>
                <input type="submit" value="Submit"/>
                <input type="reset" value="Reset"/>
            </p>
            </div>
        </form>

我已将注销放入 template.xhtml 中:

<p:menuitem value="Sign out"  actionListener="#{mngsession.logout()}" outcome="/index" />

Servlet:ManageLogin.java

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


            try {
           String username;
           String password;
           username = request.getParameter("j_username").toString();
           password = request.getParameter("j_password").toString();
           request.login(username, password);
           System.out.println(username+password);
           response.sendRedirect("template.xhtml");
           System.out.println("hi");
       } catch (Exception e) {
           System.out.println(e);
           response.sendRedirect("error.xhtml");
       }   

和 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.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>
        <servlet-name>ManageLogin</servlet-name>
        <servlet-class>beans.ManageLogin</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ManageLogin</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
    <security-constraint>
        <display-name>admin</display-name>
        <web-resource-collection>
            <web-resource-name>admin</web-resource-name>
            <description/>
            <url-pattern>/faces/users/*</url-pattern>
            <url-pattern>/faces/groups/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>bob</realm-name>
        <form-login-config>
            <form-login-page>/index.xhtml</form-login-page>
            <form-error-page>/error.xhtml</form-error-page>
        </form-login-config>
    </login-config>
    <security-role>
        <description/>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <description/>
        <role-name>user</role-name>
    </security-role>
</web-app>

最佳答案

进一步挖掘表明,使用BASIC 身份验证时也出现了类似的问题。在这种情况下,用户只有在关闭浏览器时才会注销。

如果您使用 BASIC 身份验证 - 它与浏览器绑定(bind)。需要关闭浏览器才能完全注销。要解决此问题,需要更改身份验证方法,例如更改为基于表单的身份验证。

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

此处报告了类似问题:

Logout in JSF with Security managed by Glassfish v3.1

如何配置基于表单的身份验证:

Using Form-Based Login in JavaServer Faces Web Applications

既然使用了基于 FORM 的身份验证,重要的是要知道身份验证是由容器或服务器自动管理 protected 资源的。例如,在您的情况下,您提供了:

   <security-constraint>
        <display-name>admin</display-name>
        <web-resource-collection>
            <web-resource-name>admin</web-resource-name>
            <description/>
            <url-pattern>/faces/users/*</url-pattern>
            <url-pattern>/faces/groups/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

这意味着对于任何/faces/users/* 或/faces/groups/* 调用,服务器将检查用户是否经过身份验证并具有管理员角色。如果用户没有登录,服务器将重定向到login.xhtml页面。成功登录并验证后,将显示 protected 页面。如果用户已登录但没有角色,则将显示 error.xhtml

您不需要单独的 Servlet 来使用户登录,因为服务器会为您完成此操作。您只需将用户定向到 template.xhtml 页面,容器就会完成剩下的工作。确保您的 template.xhtml 是符合 security-constraint 标记下提到的 URL 模式之一的 protected 资源。

关于java - 我无法重新登录 JSF 页面,除非关闭浏览器或重新启动 Glassfish,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28092893/

相关文章:

java - mongodb套接字中的java.lang.Throwable错误是什么意思?

jakarta-ee - java.lang.IllegalArgumentException : URLDecoder: Incomplete trailing escape () pattern

java - 我应该关闭数据库连接吗?

java - 在 JDBC 中设置 DB2 DataSource 中的当前模式

java - JPA 和 Hibernate 中的 @Id 注解

java - 我对如何使用 Java 和 Derby sql server 使用 PreparedStatements 感到困惑

java - 获取 JTextField 中的文本

java - 如何预先声明一个数组?

java - 在 .ear 文件中跨组件共享持久性单元

java - 为什么CDI使用注释参数时不满足依赖关系?