【问题标题】:How to use @SessionScoped with Guice如何在 Guice 中使用 @SessionScoped
【发布时间】:2011-08-12 05:49:44
【问题描述】:


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

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

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

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

[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) 会话中使 Identity 对象(仅它)无效?
d - 一般来说,在什么情况下我们必须使用@SessionScoped?

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

【问题讨论】:

  • 如何从 Servlet 访问 LoginAction 类?
  • 我有一个 FrontServlet,它用“injector.getInstance(LoginAction.class);”注入它

标签: java authentication guice session-scope


【解决方案1】:

[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] 我不太清楚你的意思,但是如果你想根据用户是否登录重定向到应用程序中的不同位置,你的过滤器设计是一种常见的方法。

您可以做出的一些改进:

  • 拥有一个管理会话用户的IdentitySessionScoped 服务,并确保它在Identity 实例上同步。这样,如果用户快速连续发出两个请求,您就不会遇到并发问题。
  • 宁愿注入 Providers 而不是注入 Injector(examples here) 以将您的类与 Guice 分离。
  • Inject dependencies into your classes' constructors,而不是注入字段。这样可以更轻松地进行测试(通过在测试中提供模拟/存根依赖项)。

【讨论】:

  • 如何获取现有实例?我认为“injector.getInstance()”完成了这项工作。
  • 太好了,它有效!谢谢! (响应[a]完成!)更清洁的方式怎么样? :)
  • 很高兴听到:)。我为您的其他问题添加了一些答案。
  • @Daniel :我包括 Provider 而不是您所说的滥用 Injector 使用,它工作正常。否则,我尝试实现一个“IdentityManager”是徒劳的,你能给我更多的线索吗?
  • 一个简单的实现可能只是一个带有 Identity 字段、一个 getter 和一个 setter 的 @SessionScoped bean。一旦你从你的 Authentication 类中获得了一个 Identity 实例,你可以在 IdentityManager 中设置它以便以后访问。
猜你喜欢
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 2014-08-02
  • 2013-12-11
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
相关资源
最近更新 更多