我正在尝试向基于 JSF 2 的应用程序添加身份验证。我是按照本教程开始的。
以下是我的数据库中的导出:
CREATE TABLE `authentication_groups` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(45) NOT NULL,
`description` varchar(255) default NULL,
`create_time` timestamp NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `authentication_groups` VALUES (1,'Guest','Anonymous user','2012-07-18 13:54:34'),(2,'Member','Standart user','2012-07-18 13:54:34'),(3,'Admin','Administrator','2012-07-18 13:54:34');
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(45) NOT NULL,
`password` varchar(128) NOT NULL,
`first_name` varchar(45) default NULL,
`last_name` varchar(45) default NULL,
`create_time` timestamp NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `users` VALUES (1,'admin','8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918','Samuil','Yanovski','2012-07-24 06:41:56');
CREATE TABLE `users_authentication_groups_link` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) NOT NULL,
`authentication_group_id` int(11) NOT NULL,
`create_time` timestamp NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `uag_link_users_fk` (`user_id`),
KEY `uag_link_authentication_groups_fk` (`authentication_group_id`),
CONSTRAINT `uag_link_authentication_groups_fk` FOREIGN KEY (`authentication_group_id`) REFERENCES `authentication_groups` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `uag_link_users_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `users_authentication_groups_link` VALUES (1,1,3,'2012-07-24 06:42:25');
SELECT `u`.`username` AS `username`,
`u`.`password` AS `password`,
`g`.`name` AS `name`
FROM ( (`observer`.`users_authentication_groups_link` `ug`
JOIN `observer`.`users` `u`
ON(( `u`.`id` = `ug`.`user_id` )))
JOIN `observer`.`authentication_groups` `g`
ON(( `g`.`id` = `ug`.`authentication_group_id` )));
我有一个用户名“admin”和密码“admin”(使用 SHA-256 和十六进制编码加密)的用户。
我在 Glassfish 管理控制台中创建了一个 JDBC 连接池,它正在成功地 ping 数据库。我已将此池分配给名为“jdbc/observer”的 JDBC 资源。之后在Configuration -> server-config -> Security -> Realms中,我使用以下配置创建了“ObserverRealm”:
这是我的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<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>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>jdbcRealm</realm-name>
<form-login-config>
<form-login-page>/faces/login.xhtml</form-login-page>
<form-error-page>/faces/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/faces/private/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>
和glassfish-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<security-role-mapping>
<role-name>Admin</role-name>
<principal-name>Admin</principal-name>
<group-name>Admin</group-name>
</security-role-mapping>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
</glassfish-web-app>
login.xml非常基本:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/templates/master.xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<ui:define name="content">
<p>Login to access secure pages:</p>
<h:messages />
<h:form id="loginForm">
<h:panelGrid columns="2">
<h:outputLabel for="username" value="Username:" />
<h:inputText id="username" value="#{authBackingBean.username}" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{authBackingBean.password}" />
<h:commandButton id="loginButton" value="Login" action="#{authBackingBean.login}" />
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
和AuthBackingBean:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package yanovski.observer.jsf;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Intuitiv-06
*/
@ManagedBean(name = "authBackingBean")
@RequestScoped
public class AuthBackingBean {
private static final Logger log = Logger.getLogger(AuthBackingBean.class.getName());
private String username;
private String password;
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(username, password);
} catch (ServletException e) {
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login failed!", null));
return "login";
}
//you can fetch user from database for authenticated principal and do some action
Principal principal = request.getUserPrincipal();
log.info("Authenticated user: " + principal.getName());
if (request.isUserInRole("Admin")) {
return "/admins/admins?faces-redirect=true";
} else {
return "/users/users?faces-redirect=true";
}
}
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) {
log.log(Level.SEVERE, "Failed to logout user!", e);
result = "/loginError?faces-redirect=true";
}
return result;
}
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;
}
}
你能告诉我我做错了什么吗,因为我在尝试进行身份验证时总是收到“登录失败”错误 - 使用 admin/admin 作为用户名/密码。如果您需要任何其他详细信息,请告诉我 - 如果有人想看一下,我也可以提供该项目的档案。
提前谢谢你,很抱歉这么长的帖子。:)