Как использовать @SessionScoped с Guice
Привет
В настоящее время я играю с 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] Затем я создал класс аутентификации, который входит в систему:
public class Authentication
{
@Override
public Identity authenticate(String login, String password)
{
/*some code*/
Identity identity = new Identity();
identity.setUid(user.getId());
return identity;
}
}
[3] Затем в моем сервлете я захожу в систему:
@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 моей идентичности всегда "нулевой".
Пойдем на вопросы:
a - Прежде всего, почему мой код не работает?
b. Является ли @SessionScoped эквивалентным для установки объекта в HttpSession?
Как сделать недействительным объект Identity (только он) в (http) сеанс?
г - Вообще, в каком случае мы должны были использовать @SessionScoped?
Спасибо за чтение,
Жду ваших ответов.
1 ответ
[a] Вы назначаете новый экземпляр Identity
к локальной переменной в LoginAction
, не заменяя экземпляр, управляемый Guice. Вы можете решить проблему, заполнив uid
а также name
поля на существующие Identity
Экземпляр управляется Guice.
Например, вместо
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. - Внедряйте зависимости в конструкторы ваших классов, а не вставляйте поля. Это позволяет упростить тестирование (предоставляя в тесте зависимости макета / заглушки).