Java EE 中没有这样的事件。然而。作为...的一部分JSR375 https://www.jcp.org/en/jsr/detail?id=375,容器管理的安全性将像目前一样完全重新设计疏散 http://arjan-tijms.omnifaces.org/2015/10/how-servlet-containers-all-implement.html跨不同的容器实现,并且不跨容器兼容。这在本节中概述了Java EE 8 安全 API http://www.slideshare.net/a_kosowski/devoxx-fr-ee8jsr375securityapiv1推介会。
安全 API 的参考实现已经在进行中,Soteria https://github.com/javaee-security-spec/soteria,由我的同事 Arjan Tijms 等人开发。使用新的安全 API,CDI 将用于触发身份验证事件,您只需@Observes
。关于规范的讨论发生在这个邮件列表主题 https://java.net/projects/javaee-security-spec/lists/jsr375-experts/archive/2015-03/message/61。 Soteria 尚未具体实施。
直到那时,假设FORM
基于身份验证,用户主体内部存储在会话中,如果请求中存在用户主体,而 HTTP 会话中不存在登录用户的表示,则最好的选择是手动检查 servlet 过滤器。
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
String username = request.getRemoteUser();
if (username != null && request.getSession().getAttribute("user") == null) {
// First-time login. You can do your thing here.
User user = yourUserService.find(username);
request.getSession().setAttribute("user", user);
}
chain.doFilter(req, res);
}
请注意,注册过滤器/j_security_check
不能保证正常工作,因为出于明显的安全原因,一个像样的容器会在第一个过滤器被击中之前在内部处理它(用户提供的过滤器可能会以错误的方式操纵请求,无论是无意还是有意)。
但是,如果您碰巧使用 Java EE 服务器,请使用Undertow http://undertow.io/servlet容器,例如WildFly http://wildfly.org,然后有一种更简洁的方法来挂钩其内部通知事件,然后触发自定义 CDI 事件。这是充实的这个博客 http://jdevelopment.nl/bridging-undertows-authentication-events-cdi/阿尔扬·蒂姆斯。如博客中所示,您最终可以得到如下所示的 CDI bean:
@SessionScoped
public class SessionAuthListener implements Serializable {
private static final long serialVersionUID = 1L;
public void onAuthenticated(@Observes AuthenticatedEvent event) {
String username = event.getUserPrincipal().getName();
// Do something with name, e.g. audit,
// load User instance into session, etc
}
public void onLoggedOut(@Observes LoggedOutEvent event) {
// take some action, e.g. audit, null out User, etc
}
}