Tos*_*oss 9 java security jboss login jsf-2
我刚开始学习Java EE.我的目标是为羽毛球运动员实施一个门户网站(使用EJB 3和JSF),用户可以在其中发布和分析他们的结果.
为了保持简单(事实证明它确实不是)我决定使用容器提供的安全系统(JBoss as7).在遇到一些问题后,我设法让身份验证/授权工作.但是,我有一个问题,我无法解决.
当我尝试访问受保护的页面时,我得到了正如预期的那样,被安全系统截获.但是,在我登录后,我没有被重定向到我最初请求的页面.相反,我再次被要求登录.如果我手动输入原始地址,我可以毫无困难地访问该页面.
我已经在stackoverflow上读了很多线程,但还是无法解决我的问题.如果有人能帮助我,我真的很感激!
Authentication.java:
@ManagedBean
@SessionScoped
public class Authentication {
private String username = "";
private String password = "";
private User user = new User();
@EJB
UserService service;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User getUser() {
return user;
}
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context
.getExternalContext().getRequest();
try {
Principal userPrincipal = request.getUserPrincipal();
if (userPrincipal != null) {
request.logout();
}
request.login(username, password);
user = service.find(username, password);
} catch (ServletException e) {
context.addMessage(null, new FacesMessage("Unknown login"));
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext()
.invalidateSession();
return "login";
}
}
Run Code Online (Sandbox Code Playgroud)
login.xhtml
<h:body>
<h:form>
<h:outputLabel for="username" value="Username" />
<h:inputText id="username" value="#{authentication.username}" required="true" />
<h:message for="username" />
<br />
<h:outputLabel for="password" value="Password" />
<h:inputSecret id="password" value="#{authentication.password}" required="true" />
<h:message for="password" />
<br />
<h:commandButton value="Login" action="#{authentication.login()}" />
<h:messages globalOnly="true" />
</h:form>
</h:body>
Run Code Online (Sandbox Code Playgroud)
home.xhtml
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml'
xmlns:f='http://java.sun.com/jsf/core'
xmlns:h='http://java.sun.com/jsf/html'
xmlns:ui='http://java.sun.com/jsf/facelets'
xmlns:p="http://primefaces.org/ui">
<h:head>
<link type="text/css" rel="stylesheet"
href="#{request.contextPath}/themes/cupertino/skin.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton action="login" value="Log in" />
</h:form>
</h:body>
Run Code Online (Sandbox Code Playgroud)
web.xml中
....
<display-name>BadmintonPortal</display-name>
<welcome-file-list>
<welcome-file>/pages/protected/user/user_home.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
<url-pattern>*.jsf</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>cupertino</param-value>
</context-param>
<!-- Protected area definition -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted Area - ADMIN Only</web-resource-name>
<url-pattern>/pages/protected/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted Area - USER and ADMIN</web-resource-name>
<url-pattern>/pages/protected/user/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<!-- Login page -->
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/pages/public/login.xhtml</form-login-page>
<form-error-page>/pages/public/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
<!-- System roles -->
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
Run Code Online (Sandbox Code Playgroud)
编辑:
忘了包含faces-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">
<navigation-rule>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/pages/protected/user/user_home.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
</faces-config>
Run Code Online (Sandbox Code Playgroud)
的jboss-web.xml中
<?xml version='1.0' encoding='UTF-8'?>
<jboss-web>
<context-root>BadmintonPortal</context-root>
<security-domain>java:/jaas/BadmintonPortalRealm</security-domain>
</jboss-web>
Run Code Online (Sandbox Code Playgroud)
编辑2:
工作方案
@ManagedBean
@ViewScoped
public class Authentication {
...
public Authentication() {
ExternalContext eContext = FacesContext.getCurrentInstance()
.getExternalContext();
uri = (String) eContext.getRequestMap().get(
RequestDispatcher.FORWARD_REQUEST_URI);
}
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context
.getExternalContext().getRequest();
try {
Principal userPrincipal = request.getUserPrincipal();
if (userPrincipal != null) {
request.logout();
}
request.login(username, password);
user = service.find(username, password);
context.getExternalContext().getSessionMap().put("user", user);
context.getExternalContext().redirect(uri);
} catch (ServletException e) {
context.addMessage(null, new FacesMessage("Unknown login"));
} catch (IOException e) {
e.printStackTrace();
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext()
.invalidateSession();
return "login";
}
}
Run Code Online (Sandbox Code Playgroud)
您将使用JSF表单接管登录部分,该表单在提交时在JSF托管bean中执行编程登录.如果您使用的是直接提交到容器管理的身份验证URL的纯HTML表单,j_security_check如本答案第一部分所述,那么您确实会自动重定向到初始页面.
但是,由于您自己使用JSF自行登录,因此您还应该自己使用JSF导航到初始页面.由于登录页面通常由服务器端转发打开RequestDispatcher#forward(),因此最初请求的页面可用作请求属性,其名称为RequestDispatcher.FORWARD_REQUEST_URI常量.在JSF术语中,因此可用如下:
String originalURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
Run Code Online (Sandbox Code Playgroud)
(请记住,它返回的案例有一个后备网址null,即直接打开它而不首先点击受限制的URL)
收集它的最佳位置是@ViewScoped与登录页面关联的bean 的(post)构造函数.使用当前会话范围的bean方法,最好使它成为视图范围的方法,并且在登录期间显式地将其User放入会话范围中,如下所示:
externalContext.getSessionMap().put("user", user);
Run Code Online (Sandbox Code Playgroud)
通过这种方式,用户可以#{user}直接使用而不是#{authentication.user}.
| 归档时间: |
|
| 查看次数: |
7449 次 |
| 最近记录: |