JSF请求范围的托管bean http-session导致实例化 [英] JSF request-scoped managed bean http-session causes in-instantiation

查看:167
本文介绍了JSF请求范围的托管bean http-session导致实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用SessionFilter servlet验证用户,然后向他们授予系统访问权限.我的受限制文件位于名为"com.shadibandhan.Restricted"的文件夹中. 会话过滤器工作正常.

I'm using a SessionFilter servlet for validating users and then giving access of the system to them. My restricted files are in a folder named "com.shadibandhan.Restricted". Session filter is working fine.

这是sessionfilter servlet的相关代码

here's the relevant code of the sessionfilter servlet

@Override
public void doFilter(ServletRequest req, ServletResponse res,
        FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    String servletPath = request.getServletPath();
    String contextPath = request.getContextPath();
    String remoteHost = request.getRemoteHost();
    String url = contextPath + servletPath;
    boolean allowedRequest = false;

    if (urlList.contains(servletPath)) {
        allowedRequest = true;
    }

    if (!allowedRequest) {
        HttpSession session = request.getSession(false);
        if (null == session) {

            System.out.println("Session is not present");
            response.sendRedirect(contextPath);
            return;

        } if (null != session) {
            //String loggedIn = (String) session.getAttribute("sb_logged_in");
            System.out.println("Session is present");
            System.out.println("\nSession no. is = " + session.getId());

            if (session.getAttribute("logged-in") == "true") {
                System.out.println("Session logged-in attribute is true, " + session.getAttribute("sessionUsername") + " is logged in.");

                //ServletContext context = request.getServletContext();
                RequestDispatcher dispatcher = request.getRequestDispatcher(servletPath);
                dispatcher.forward(request, response);
            } else {
                System.out.println("Session logged-in attribute is not true");
                response.sendRedirect(contextPath);
            }
        }
    }

    chain.doFilter(req, res);
}

现在,当用户登录时,我将其用户名和个人资料ID放在httpsession中,这是与登录页面绑定的bean.

Now, when a user logs in, I put his username and profile id in the httpsession, Here's is the bean that is bound with the login page.

@ManagedBean
@SessionScoped
public class UserLoginManagedBean {

    private User user = null;
    private String username = null;
    private String password = null;
    private ServiceProvider server = null;
    HttpServletRequest request = null;
    HttpServletResponse response = null;
    HttpSession session = null;
    private Date date;
    private int profileActiveness=0;
    private int profileActivenessPercentage=0;

    public UserLoginManagedBean() {
        this.user = new User();
        this.server = ServiceProvider.getInstance();
    }

    public String validateLogin() {

        System.out.println("Inside validate login");
        boolean isUserValid = false;

        System.out.println(this.username + " " + this.password);

        isUserValid = this.authenticate(username, password);

        if (isUserValid) {
            //this.user = found;
            System.out.println("User is valid---Redirecting to messages.xhtml");
            return "com.shadibandhan.Restricted/profile.xhtml?faces-redirect=true";

        } else {
            //addGlobalErrorMessage("Unknown login, please try again");
            return null;
        }
    }

    public boolean authenticate(String username, String password) {
        boolean isUserValid = false;
        String status = null;

        //isUserValid = this.server.authenticateUser(this.username, this.password);

        this.user = (User) this.server.getRecordByTwoColumns(User.class, "username" , this.username, "password", this.password);

        if(null != this.user){
            isUserValid = true;
        }else{
            isUserValid = false;
        }

        if (isUserValid) {

            FacesContext context = FacesContext.getCurrentInstance();
            this.request = (HttpServletRequest) context.getExternalContext().getRequest();
            this.response = (HttpServletResponse) context.getExternalContext().getResponse();
            this.session = request.getSession(true);
//                 if there's no session, it'll creat a new one due to the true flag


            status = this.updateUserRecord();


            if (status.equals("success")) {
                if (null != this.session) {

                    session.setAttribute("sessionUsername", this.user.getUsername());
                    session.setAttribute("sessionProfileId", this.user.getProfile().getProfileId());
                    session.setAttribute("logged-in", "true");

                    System.out.println("Session username is --->" + session.getAttribute("sessionUsername"));
                }

            } else {
                isUserValid = false;
                FacesMessage msg = new FacesMessage("Something went wrong");
                FacesContext.getCurrentInstance().addMessage(null, msg);
            }
        }

        return isUserValid;
    }

    public String logOut() {
        FacesContext context = FacesContext.getCurrentInstance();
        System.out.println("inside logout method");
        this.request = (HttpServletRequest) context.getExternalContext().getRequest();

        if (null != this.request) {

            this.session = request.getSession(false);
            session.invalidate();
            System.out.println("Session is now invalidated");
            return "../index.xhtml?faces-redirect=true";
        } else {
            System.out.println("You're already signed out");
            return null;
        }
    }

    private String updateUserRecord() {
        String status = null;

       Date lastLoginDate=this.user.getLastLogin();
       Date currentDate= new Date();
       this.profileActiveness=this.user.getProfileActiveness();


                SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");

        try {
            lastLoginDate = format.parse(lastLoginDate.toString());
            currentDate = format.parse(currentDate.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }    

        // Get msec from each, and subtract.
        long diff = currentDate.getTime() - lastLoginDate.getTime();
        long diffSeconds = diff / 1000;         
        long diffMinutes = diff / (60 * 1000);         
        long diffHours = diff / (60 * 60 * 1000);                      
        System.out.println("Time: " + diff + " .");
        System.out.println("Time in seconds: " + diffSeconds + " seconds.");         
        System.out.println("Time in minutes: " + diffMinutes + " minutes.");         
        System.out.println("Time in hours: " + diffHours + " hours.");
        if(diffHours<12)
        {
            if(profileActiveness<8){
            profileActiveness++;
            profileActivenessPercentage=(int) (profileActiveness*12.5);
            this.user.setProfileActiveness(this.profileActiveness);
            }
            }
        if(diffHours>71)
        {
            if(profileActiveness>2){
            profileActiveness-=2;
            profileActivenessPercentage=(int) (profileActiveness*12.5);
            this.user.setProfileActiveness(this.profileActiveness);
            }
            else{
            profileActiveness=0;
            }
        }



        this.user.setLastLogin(this.getCurrentDate());
        this.user.setLoginStatus(true);

        status = this.server.updateObject(this.user);

        return status;
    }

    // ...
}

然后,在另一个名为MessagesManagedBean的托管Bean(请求范围)中,当我尝试在用户登录后获取概要文件ID时,它就像一个超级按钮.

And, in another managed bean (request-scoped) named, MessagesManagedBean, when i try to get the profile id after the user has logged in, it works like a charm.

现在,我在这里有两个问题:

Now, I've two questions here :

  1. 每当我尝试从具有以下内容的受限文件夹访问页面时 与之绑定的具有与http会话相关的一些代码的bean 就像在这种情况下的MessagesManagedBean,它给了我一个不能 实例化bean异常,因为我在 构造函数,为什么?
  2. 即使我没有登录,它也会调用Bean 构造函数,每当我尝试访问与其绑定的页面时.
  1. Whenever I try to access a page from the restricted folder that has a bean bound with it having some code related to the http session as in this case the MessagesManagedBean, It gives me a Can't instantiate bean exception because i'm getting the attribute in the constructor, why ?
  2. Even, when I'm not logged in, it calls the bean constructor, whenever i try to access the page bound with it.

推荐答案

调用response.sendRedirect()后,您将通过chain.doFilter()继续请求. sendRedirect()仅使用新URL设置Location响应标头,然后浏览器将处理新URL.但是,如果您按chain.doFilter()继续请求,那么整个JSF流程仍将执行.

You're continuing the request by chain.doFilter() after calling response.sendRedirect(). The sendRedirect() merely sets a Location response header with the new URL which the browser will then handle. But if you continue the request by chain.doFilter(), then the whole JSF process will still be executed.

您需要在sendRedirect()调用之后添加return;语句以退出过滤器.

You need to add a return; statement after the sendRedirect() call to exit the filter.

} else {
    System.out.println("Session logged-in attribute is not true");
    response.sendRedirect(contextPath);
    return;
}


无关与具体问题无关,您在会话范围内的Bean中遇到了一个主要的设计错误.您永远不应将HTTP请求,响应和会话分配为Bean的实例变量.这使您的会话范围的bean线程不安全. 删除所有这些属性,并仅在完全相同的方法块内将它们声明为threadlocal.


Unrelated to the concrete problem, you've a major design mistake in your session scoped bean. You should never assign the HTTP request, response and session as an instance variable of the bean. This makes your session scoped bean threadunsafe. Remove all those properties and declare them threadlocal inside the very same method block only.

这篇关于JSF请求范围的托管bean http-session导致实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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