Webfilter登录机制总是需要两次尝试 [英] Webfilter login mechanism takes always two attempts

查看:82
本文介绍了Webfilter登录机制总是需要两次尝试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一种登录机制,用于在Webfilter内对用户进行身份验证.单击登录按钮并且凭据有效后,它应该重定向.

I'm developing a login mechanism that authenticates the user within a webfilter. When the login-button is clicked and the credentials are valid it's supposed to redirect.

我遇到的问题是,第一次按下登录按钮后,Webfilter似乎没有凭据.日志记录表明,在应该存储凭据的@SessionScoped bean中不存在参数.

The problem I have is, that the Webfilter doesn't seem to have the credentials after the login button has been pushed the first time. Logging suggests that the parameters are not present in the @SessionScoped bean that is supposed to store the credentials.

要使其真正登录,我必须再次按下登录按钮(这次我完全不用输入凭据也无所谓),然后重新定向.

For it to actually log in, I have to push the login-button again (this time it does not matter wheter I put in the credentials at all) and then I get redirected.

当我尝试使会话无效时,也会发生相同的问题.我在页面上,单击按钮以使页面失效,页面再次显示,并且仅在刷新后,我才重定向到登录页面.

The same problem also occurs when I try to invalidate the session. I'm on the page, click the button to invalidate, the page gets shown again and only after a refresh I get redirected to the login page.

验证用户并在会话无效的情况下进行重定向的整个过程都在Web过滤器中进行.

The whole process of validating the user and redirecting in case the session is not valid takes place within a webfilter.

我认为问题是,参数和其他操作仅在处理Web过滤器后才生效,但是这些机制应该如何起作用?我到处都读到,应该在Web筛选器中实现自我实现的登录机制,这样做是很有意义的.

I assume the problem is, that parameters and other actions only take effect after the webfilter has been processed, but then, how are these mechanisms supposed to work? I've read everywhere that self-implemented login-mechanisms should be implemented in a webfilter, and it makes perfect sense to do so.

我添加了基本代码.(不是所有的东西,很多)

I've added the essential code. (not everything, it's quite a lot)

login.xhtml

login.xhtml

<h:body>

<h1>Login</h1>
<h:form id="loginForm">
    <h:message for="loginForm" />
    <h:outputLabel value="Username" />
    <h:inputText value="#{CRMSession.username}"></h:inputText>
    <br />
    <h:outputLabel value="Passwort" />
    <h:inputSecret value="#{CRMSession.passHash}"></h:inputSecret>
    <h:commandButton action="submit" value="submit"></h:commandButton>
</h:form>

Webfilter(缩短):(我取出了整个Cookie的一部分,因为目前所有注释都已被注释掉,错误不可能存在.我只是取出来使整个内容可读)

Webfilter (shortened): (I took out the whole cookie part, since that's all commented out at the moment the error can't be there. I just took it out to make the whole thing readable)

@WebFilter(filterName = "SP", urlPatterns = "/*")
public class SessionProvider implements Filter {

private final static String AUTH_COOKIENAME = "kimcrmstoken";
private final static String LOGINURL = "./login.jsf";
private final static String INDEXURL = "./index.jsf";

@Inject
CRMSession crmsession;
@Inject
LoggingProvider loggingProvider;
@Inject
LoginHandler loginHandler;
@Inject
ConfigUpdates configUpdates;
@Inject
CRMContext context;
@Inject
UserHandler userHandler;
Logger logger;

@Override
public void destroy() {
    // TODO Auto-generated method stub

}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    Cookie[] cookies = req.getCookies();
    logger = loggingProvider.getLogger(this.getClass().getName());
    logger.log(LogLevel.INFO, "SessionProvider working");


    if(credentialsPresent())
        logger.log(LogLevel.INFO, "credentials present");
    else
        logger.log(LogLevel.INFO, "NO credentials present");
    if(crmsession.isAuthenticated())
        logger.log(LogLevel.INFO, "Session authenticated");

    if (!crmsession.isAuthenticated() && credentialsPresent()) {
        /*
         * Session ist nicht authentifiziert, aber credentials sind
         * vorhanden
         */
        logger.log(LogLevel.INFO, "session not authenticated but credentials present");
        try {
            if (!loginHandler.validateCredentials()) {
                logger.log(LogLevel.INFO, "Credentials invalit");
                crmsession.setPassHashToNull();
                crmsession.setAuthenticated(false);
                resp.sendRedirect(LOGINURL);
            } else {
                logger.log(LogLevel.INFO, "Credentials valid");
                crmsession.setAuthenticated(true);
                crmsession.setLoggedIn(true);
                crmsession.setJustloggedin(true);

            }
        } catch (SQLException e) {
            // wird erreicht wenn bei der Userauthentifizierung eine
            // SQLexception geworfen wird
            logger.log(LogLevel.ALERT, "Fehler in User Authentifizierung");
            throw new ServletException(e.getMessage());
        }
    }




    /*
     * prüfen ob in der Session ein username und ein Passwort vorhanden
     * sind, wenn nicht->loginpage
     */
    if (!crmsession.isAuthenticated()) {
        if (req.getRequestURI().contains("/login.jsf")) {
            logger.log(LogLevel.INFO, "PATH is login.jsf");
            crmsession.setAuthenticated(false);
            chain.doFilter(request, response);
            return;
        }
        if (!credentialsPresent()) {
            logger.log(LogLevel.INFO, "NO Pass or username, redirecting");
            crmsession.setAuthenticated(false);
            resp.sendRedirect(LOGINURL);
            return;
        }
    }


    }

    /*
     * Weiterleitung zum index nach der anmeldung
     */
    if(crmsession.isAuthenticated() && crmsession.isJustloggedin()){
        crmsession.setJustloggedin(false);
        resp.sendRedirect(INDEXURL);
    }

    // Fortfahren
    logger.log(LogLevel.FINEST, "SessionProvider done");
    chain.doFilter(request, response);

}

@Override
public void init(FilterConfig arg0) throws ServletException {
    // TODO Auto-generated method stub

}

public boolean credentialsPresent() {
    if (crmsession.getUsername() == null)
        return false;
    if (crmsession.getPassHash() == null)
        return false;
    if (crmsession.getUsername().equals(""))
        return false;
    if (crmsession.getPassHash().equals(""))
        return false;
    return true;
}

}

会话无效的相同问题:

<html 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">


index

<h:form>
    <h:commandButton action="#{index.clearSession}" value="clear">
</h:commandButton>
</h:form>
</html>

Backing Bean:

Backing Bean:

import java.io.Serializable;

import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpSession;

@RequestScoped
@Named
public class Index implements Serializable {

public String clearSession(){
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
    session.invalidate();
    return "./index.jsf";
}
}

推荐答案

看来您对过滤器的错误负责.它的责任是不执行实际的登录(或注销).它的责任是根据登录用户限制对请求资源的访问.

It appears that you got the responsibility of the filter wrong. Its responsibility is not to perform the actual login (or logout). Its responsibility is to restrict access to the requested resource based on the logged-in user.

您应该在与登录表单关联的请求/视图作用域后备bean的操作方法中执行实际登录(和注销).成功登录/注销后,您应该重定向到目标页面.筛选器应仅检查是否允许当前登录的用户访问所请求的资源.如果是,则继续过滤器链.如果不是,则重定向到登录页面或发送401/403.

You should perform the actual login (and logout) in the action method of the request/view scoped backing bean associated with the login form. After a successful login/logout you should redirect to the target page. The filter should just check if the currently logged-in user is allowed to access the requested resource. If it is, then continue filter chain. If it is not, then redirect to login page or send 401/403.

请注意,您的过滤器不包含JSF资源或Ajax请求.在此答案中,您可以找到JSF感知认证过滤器的完整示例:

Note that your filter doesn't cover JSF resource or ajax requests. In this answer you can find a complete example of a JSF aware authentication filter: Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same.

这篇关于Webfilter登录机制总是需要两次尝试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆