使用 Servlet 3.0 以编程方式控制登录
Posted
技术标签:
【中文标题】使用 Servlet 3.0 以编程方式控制登录【英文标题】:Programmatically control login with Servlet 3.0 【发布时间】:2011-09-05 13:57:21 【问题描述】:我已经测试了 Glassfish 3.0.1 中的默认安全容器,得出的结论是我不会再花时间在这上面了。相反,我想自己控制验证。但我需要一些指导才能让我走上正轨。
目前我有一个具有登录/注销功能的 UserBean(见下文)。而且我不想使用 *j_security_check* 内置容器,而是使用核心 JSF 2.0。
我的问题是;
-
如果用户未登录(如果访问某些文件夹),我是否需要 ServletFilter 来重定向流量?
用户成功登录后如何存储用户密码?
感谢任何帮助或示例链接,问候克里斯。
PS。请原谅我把两个问题聚集在一起
@ManagedBean
@SessionScoped
public class UserBean
private AuthenticateUser authenticateUser;
...
public String login()
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
JsfUtil.log("Username : " +authenticateUser.getUserName());
JsfUtil.log("Password : " +authenticateUser.getPassword());
AuthenticateUser authRequest = authenticationFacade.find(authenticateUser);
try
if(!authRequest.equals(authenticateUser))
return "/loginError";
request.login(authenticateUser.getUserName(), authenticateUser.getPassword());
return "";
catch(ServletException e)
JsfUtil.addErrorMessage(e, "Incorrect username or password, please try again.");
return "/loginError";
...
public String logOut()
String result = "/index?faces-redirect=true";
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try
request.logout();
catch (ServletException e)
JsfUtil.log("Failed to logout user!" +e.getRootCause().toString());
result = "/loginError?faces-redirect=true";
return result;
【问题讨论】:
【参考方案1】:如果你想使用request.login()
,那么你应该已经在容器中配置了一个代表用户数据库的领域。但是您似乎已经用一些AuthenticationFacade
替换了Realm。在这种情况下,request.login()
对您没有用处。
您只需将用户置于会话范围内并对其进行拦截。这是一个启动示例:
@ManagedBean
@SessionScoped
public class UserManager
@EJB
private UserService userService;
private String username;
private String password;
private User current;
public String login()
current = userService.find(username, password);
if (current == null)
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unknown login, try again"));
return null;
else
return "userhome?faces-redirect=true";
public String logout()
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "index?faces-redirect=true";
public boolean isLoggedIn()
return current != null;
// Getters/setters (but do NOT provide a setter for current!)
像这样进行身份验证时,您肯定需要filter 来限制访问。使用容器管理的安全性时,您通常会将其指定为 <url-pattern>
或 <security-constraint>
。但没有它,你必须把它拿在手中。很高兴知道 JSF 托管 bean 在任何范围内都由它们的托管 bean 名称作为键。
UserManager userManager = ((HttpServletRequest) request).getSession().getAttribute("userManager");
if (userManager == null || !userManager.isLoggedIn())
((HttpServletResponse) response).sendRedirect("login.xhtml");
else
chain.doFilter(request, response);
将上述过滤器映射到所需的 URL 模式。
当您仍想重新考虑使用容器管理的身份验证时,以下相关答案可能会有用:
Java EE Login Page Problem(和Configuring Realm in Glassfish) Performing user authentication in Java EE / JSF using j_security_check【讨论】:
感谢您的超级快速回答。也许不使用应用容器中的领域是不明智的。但是当我尝试使用我的表格结构/设计时,我偶然发现了巡逻。对容器领域的黑匣子来说,感觉就像是一个黑盒子。但是使用 ServletFilter 我仍然可以限制对根目录和其他文件夹的所有访问。所以我明天试一试。再次感谢。【参考方案2】:如果您正在使用 JDBC 领域安全性,请注意。在 Glassfish 管理控制台中配置领域的字段中有一些固定/预期的词。
在 JAAS Context: 文件中,您必须输入:jdbcRealm。此关键字使安全容器使用预期的 JDBC 领域。如果您键入其他内容,它将不起作用。
这是一个很好的例子,由 Gordan Jugo 完成; Netbeans/Glassfish JDBC Security Realm
【讨论】:
以上是关于使用 Servlet 3.0 以编程方式控制登录的主要内容,如果未能解决你的问题,请参考以下文章
Servlet 3.0 的 MultipartResolver 的 Spring 4 Java 配置
在 servlet 中以编程方式调用过滤器(使用码头/火花创建)?