如何将 @SessionScoped 与 Guice 一起使用

发布于 2024-11-03 08:22:39 字数 2107 浏览 0 评论 0原文


我目前正在使用 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*/
}

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

< strong>[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");
    }
}

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

嗯,这段代码不工作。我的身份的 uid 始终为“null”。

让我们来提问:

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

感谢您的阅读,
等待您的答复。

Hi
I am currently playing with Guice and @SessionScoped. To give it more sense, I decided to build a (very simple) authentication process.

Below, I will explain each step I have done. Then I will ask you some questions.

[1] I have create an Identity class which represents a person (guest or user) :

@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*/
}

[2] Next, I created an Authentication class that log-in user:

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

        Identity identity = new Identity();
        identity.setUid(user.getId());
        return identity;
    }
}

[3] Then, in my Servlet, I log-in the user :

@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");
    }
}

[4] Finally, I create a Filter that show me if user is authenticated :

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

Well, this code is not working. My Identity's uid is always "null".

Let's go for questions :

a - First of all, Why did my code not works ?
b - Is @SessionScoped equivalent to set the object in HttpSession ?
c - How to invalidate the Identity object (only it) in (http)session ?
d - Generally, In which case did we have to use @SessionScoped?

Thanks you for reading,
Waiting your answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↙厌世 2024-11-10 08:22:39

[a] 您将 Identity 的新实例分配给 LoginAction 中的局部变量,而不是替换由 Guice 管理的实例。您可以通过填充 Guice 管理的现有 Identity 实例上的 uidname 字段来解决该问题。

例如,

identity = auth.authenticate("login","password"); 

您可以说:

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

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

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

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

您可以进行的一些改进:

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

[a] You're assigning a new instance of Identity to a local variable in LoginAction, not replacing the instance managed by Guice. You could solve the problem by populating the uid and name fields on the existing Identity instance managed by Guice.

For example, instead of

identity = auth.authenticate("login","password"); 

you could say:

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

There are cleaner ways to do it, but you get the idea.

[b]/[d] That's correct: @SessionScoped is equivalent to setting a variable in the HttpSession, and this is the kind of situation that you would use it. You'll need it for objects that need to be unique across sessions, but need to be available for every request.

[c] I'm not quite sure what you mean, but if you're wanting to redirect to different places in the app depending on whether the user is logged in, your filter design is a common way to do that.

Some improvements that you could make:

  • Have a SessionScoped service that manages the session's user's Identity, and make sure it's synchronized on the Identity instance. That way you won't have concurrency troubles if a user makes two requests in quick succession.
  • Prefer injecting Providers instead of injecting the Injector(examples here) to decouple your classes from Guice.
  • Inject dependencies into your classes' constructors, instead of injecting fields. This allows for easier testing (by providing mock/stub dependencies in tests).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文