如何在Guice中使用@SessionScoped

Pie*_*rre 5 java authentication guice session-scope

嗨,
我目前正在玩Guice和@SessionScoped.为了更有意义,我决定构建一个(非常简单的)身份验证过程.

下面,我将解释我所做的每一步.然后我会问你一些问题.

[1] 我创建了一个代表一个人(访客或用户)的Identity类:

@SessionScoped
public class Identity implements Serializable
{
    private String uid;
    private String name;

    public boolean isAuthenticate()
    {
        return uid != null;
    }

    public void logout()
    {
        this.uid = null;
    }

    /*Setters-Getters*/
}
Run Code Online (Sandbox Code Playgroud)

[2] 接下来,我创建了一个登录用户的Authentication类:

public class Authentication
{
    @Override
    public Identity authenticate(String login, String password)
    {
        /*some code*/

        Identity identity = new Identity();
        identity.setUid(user.getId());
        return identity;
    }
}
Run Code Online (Sandbox Code Playgroud)

[3] 然后,在我的Servlet中,我登录用户:

@RequestScoped
public class LoginAction
{
    @Inject
    Injector injector;

    protected void login(HttpServletRequest req, HttpServletResponse resp)
    {
            Identity identity = injector.getInstance(Identity.class);
            Authentication auth = new Authentication();
            identity = auth.authenticate("login","password");
    }
}
Run Code Online (Sandbox Code Playgroud)

[4] 最后,我创建了一个过滤器,显示用户是否经过身份验证:

@Singleton
public class SecurityFilter implements Filter
{
    @Inject
    private Injector injector;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
    {
        Identity identity = injector.getInstance(Identity.class);

        if(identity.isAuthenticate())
        {
            System.err.println("USER");
        }
        else
        {
            System.err.println("GUEST");
        }

        chain.doFilter(request, response);
    }
}
Run Code Online (Sandbox Code Playgroud)

好吧,这段代码不起作用.我的身份的uid总是"空".

我们来回答问题:

a - 首先,为什么我的代码不起作用?
b - @SessionScoped是否相当于在HttpSession中设置对象?
c - 如何在(http)会话中使Identity对象(仅限于它)无效?
d - 通常,在哪种情况下我们必须使用@SessionScoped?

谢谢你的阅读,
等待你的答案.

Dan*_*iel 9

[a]您正在Identity为一个局部变量分配一个新实例LoginAction,而不是替换Guice管理的实例.您可以通过填充Guice管理的现有实例上的uidname字段来解决问题Identity.

例如,而不是

identity = auth.authenticate("login","password"); 
Run Code Online (Sandbox Code Playgroud)

你可以说:

Identity identity = injector.getInstance(Identity.class);
Authentication auth = new Authentication();
Identity authenticated = auth.authenticate("login","password");
identity.setUid(authenticated.getUid());
identity.setName(authenticated.getName());
Run Code Online (Sandbox Code Playgroud)

有更简洁的方法可以做到这一点,但你明白了.

[b]/[d]这是正确的:@SessionScoped相当于在中设置一个变量HttpSession,这就是你要使用它的情况.对于需要在会话中唯一的对象,您需要它,但需要为每个请求提供.

[c]我不太清楚你的意思,但是如果你想根据用户是否登录而重定向到应用程序的不同位置,你的过滤器设计是一种常见的方法.

您可以做出一些改进:

  • 有一个SessionScoped管理会话用户的服务Identity,并确保它在Identity实例上同步.这样,如果用户快速连续发出两个请求,您就不会遇到并发问题.
  • 更喜欢注入Providers而不是注入Injector(这里的例子)来将你的类与Guice分离.
  • 将依赖项注入类的构造函数,而不是注入字段.这允许更容易的测试(通过在测试中提供模拟/存根依赖性).