如何使用Java EE 6实现自我管理的Web用户?

Ale*_*lex 8 java authentication

我想创建一个具有自注册用户的简单Web应用程序.换句话说,我希望用户能够注册,登录,管理他们的数据,注销,如果他们想要,删除他们的帐户.这是一个业余爱好项目,只是为了学习新东西,我决定尝试使用最新的Java EE创建这个网站,我以前没用过.

我花了几个小时阅读有关JAAS,身份验证领域等的内容,我找到了许多基于服务器上定义的用户和角色实现安全性的方法(如GlassFish),但我没有找到任何关于如何实现解决方案的示例或指示用户可以在网页上填写注册表单,成为系统中的用户.当然,我可以简单地拥有一个带有用户名和密码哈希值的数据库表,并手动实现所有内容,但它失败了.

因此,我的问题是:

  1. Java EE的标准身份验证和安全框架是否适合实现用户可以自行管理的应用程序?或者它更"企业"并依赖外部认证和用户管理?
  2. 如果我很容易做到我需要的,请指出一些样品.

谢谢!

Mau*_*rry 1

J2EE 在这方面不太擅长。不过我已经在应用程序中做到了这一点。我的应用程序使用的(唯一)数据库中有一个用户表,并且我已在 web 应用程序的 META-INF 目录中的 context.xml 文件中声明了一个领域(我正在使用 tomcat 顺便说一句):

<Realm className="org.apache.catalina.realm.DataSourceRealm"
        dataSourceName="jdbc/fantastico" debug="99" localDataSource="true"
        digest="MD5" roleNameCol="ROLE" userCredCol="PASSWORD"
        userNameCol="USERNAME" userRoleTable="user_roles"
        userTable="active_users"/>
Run Code Online (Sandbox Code Playgroud)

数据源与应用程序其余部分中使用的数据源相同,并在 tomcat 安装的 server.xml 中声明(以便我可以指向另一个数据库而不更改 .war 文件)。

我在 web.xml 文件中使用角色保护了位置,确保我已将注册页面和登录页面置于不受保护的状态:

<security-constraint>
    <display-name>Administrators</display-name>
    <web-resource-collection>
        <web-resource-name>admin</web-resource-name>
        <description>Admin</description>
        <url-pattern>/admin</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
        <http-method>HEAD</http-method>
        <http-method>PUT</http-method>
        <http-method>OPTIONS</http-method>
        <http-method>TRACE</http-method>
        <http-method>DELETE</http-method>
    </web-resource-collection>
    <auth-constraint>
        <description>Allow access only to administrators</description>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>
Run Code Online (Sandbox Code Playgroud)

我已经指定了 <login-config> 部分,其中 FORM 作为身份验证方法:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name/>
    <form-login-config>
        <form-login-page>/login/</form-login-page>
        <form-error-page>/login/error</form-error-page>
    </form-login-config>
</login-config>
Run Code Online (Sandbox Code Playgroud)

由于领域被声明为使用 MD5 摘要,因此必须将密码的 MD5 存储在数据库中:

private static final char HEX[] = "0123456789abcdef".toCharArray();


public static String hex(byte data[]) {
    char[] chars = new char[2*data.length];
    for (int i=0; i < data.length; i++) {
        int low = data[i] & 0x0f;
        int high = (data[i] & 0xf0) >> 4;
        chars[i*2] = HEX[high];
        chars[i*2 + 1] = HEX[low];
    }
    return new String(chars);
}

public static byte[] hash(byte data[]) {
    synchronized (DIGEST) {
        DIGEST.reset();
        return DIGEST.digest(data);
    }
}

public static String hash(String value) {
    try {
        byte data[] = hash(value.getBytes("UTF-8"));
        return hex(data);
    } catch (UnsupportedEncodingException e) {
        // Cannot happen: UTF-8 support is required by Java spec
        LOG.error("Failed to generate digest", e);
        throw new RuntimeException(e.getMessage());
    }
}
Run Code Online (Sandbox Code Playgroud)

在登录表单中,只要需要身份验证,tomcat 就会显示,我添加了一个指向注册表单的链接:

...

<form id="login-form" action="j_security_check" method="post">
    <table>
        <tbody>
            <tr>
                <td><label for="username">User name:&nbsp;</label></td>
                <td><input type="text" name="j_username" id="username" /></td>
            </tr>
            <tr>
                <td><label for="password">Password:&nbsp;</label></td>
                <td><input type="password" name="j_password" id="password" /></td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td><input type="submit" id="submit" name="submit" value="Login"></td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td><a href="../reg/create">I'm a new user</a></td>
            </tr>
        </tbody>
    </table>
</form>
Run Code Online (Sandbox Code Playgroud)

...

现在,当提交注册表单时,我将用户存储在数据库中,并发送重定向以自动登录用户:

...

response.sendRedirect(request.getContextPath()
        + "/j_security_check?j_username="
        + URLEncoder.encode(getEmail(), "UTF-8")
        + "&j_password="
        + URLEncoder.encode(password, "UTF-8"));
Run Code Online (Sandbox Code Playgroud)

...

希望这会有所帮助