我想创建一个具有自我注册用户的简单Web应用程序。换句话说,我希望用户能够注册,登录,管理其数据,注销,并在需要时删除其帐户。这是一个业余项目,只是为了学习新知识,我决定尝试使用最新的Java EE创建此网站,而我以前从未使用过。

我花了几个小时阅读有关JAAS,身份验证领域等的内容,我发现了许多方法可以根据服务器上定义的用户和角色(例如GlassFish)来实现安全性,但是我没有找到任何示例或如何实现解决方案的指针。用户只需在网页上填写注册表格即可成为系统中的用户。当然,我可以简单地创建一个包含用户名和密码哈希的数据库表,并手动实现所有功能,但这违背了目的。

因此,我的问题是:

  • Java EE的标准身份验证和安全框架是否适合实现用户可以自行管理的应用程序?还是更“企业化”并依靠外部身份验证和用户管理?
  • 如果可以轻松完成我需要的操作,请给我指出一些示例。

  • 谢谢!

    最佳答案

    J2EE在这方面不是很好。我已经在应用程序中做到了。
    我在应用程序使用的(唯一的)数据库中有一个用户表,并且已经在Web应用程序的META-INF目录中的context.xml文件中声明了一个领域(我使用的是tomcat btw):

    <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"/>
    

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

    我已在web.xml文件中使用角色保护了位置,并确保将注册页面和登录页面保留为uprotected:
    <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>
    

    我指定了一个部分,其中FORM作为auth方法:
    <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>
    

    由于该领域被声明为使用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());
        }
    }
    

    在登录表单中,只要需要身份验证,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>
    

    ...

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

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

    ...

    希望这会有所帮助

    09-10 07:28
    查看更多