Java EE声明性安全性,无法为JDBC领域用户加载组

时间:2012-05-07 13:40:23

标签: java-ee jdbcrealm declarative-security

这是我在这里的第一篇文章。关于声明性Java EE安全性,我有两个问题:(1)基于文件的身份验证和(2)基于数据库的身份验证。我为这两个问题附上了配置的相关部分。我在Glassfish 3.1.1上运行代码。也提前感谢您的帮助。

我也在寻找我的问题的答案,并找到了一些有用的例子,我也把它放在信息的底部。我试图跟随它们,所以配置的当前状态可以包含这些样本的详细信息,但它们没有解决问题。

- 如果"默认主体到角色映射"基于文件的身份验证可以正常工作。被勾选,否则即使将主体添加到映射中它也不起作用。我可能没有以正确的方式配置某些东西。

基于-DB的身份验证。就授权而言,它无法正常工作,因为无法读取组名。详情见下文。认证可以正常工作,即用户被识别。我甚至尝试重命名表格,以避免与Glassfish的内部内容发生潜在的名称冲突......

(1)基于文件的身份验证: 文件域,2个用户:用户,管理员添加并分配给组:用户和管理员 (configurations / server-config / security / realms / file - > Manage Users)

配置/服务器配置/安全 默认主体到角色映射"勾选" - >有用 默认主体到角色映射"未勾选" - >即使将其添加到安全性映射中,它也不起作用。

web.xml

[...]
    <security-constraint>
        <display-name>Admin Pages</display-name>
        <web-resource-collection>
            <web-resource-name>Protected Admin Area</web-resource-name>
            <description/>
            <url-pattern>/faces/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/>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <security-constraint>
        <display-name>User Pages</display-name>
        <web-resource-collection>
            <web-resource-name>Protected Users Area</web-resource-name>
            <description/>
            <url-pattern>/faces/users/*</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/>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>  
        <auth-method>FORM</auth-method>
        <realm-name>file</realm-name>
        <form-login-config>
            <form-login-page>/faces/loginForm.xhtml</form-login-page>
            <form-error-page>/faces/loginError.xhtml</form-error-page>
        </form-login-config>
    </login-config>

[...]

glassfish-web.xml:

<glassfish-web-app>
    <security-role-mapping>
        <role-name>admin</role-name>
        <group-name>admin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>user</role-name>
        <group-name>user</group-name>
    </security-role-mapping>  
</glassfish-web-app>

没有默认主体映射的记录错误:

  1. 没有Principal映射到Role [user]。
  2. 没有Principal映射到Role [admin]。

  3. Log without the default principal mapping:
        <security-role-mapping>
            <role-name>admin</role-name>
            <group-name>admin</group-name>
            <principal-name>admin</principal-name>
        </security-role-mapping>
        <security-role-mapping>
            <role-name>user</role-name>
            <group-name>user</group-name>
            <principal-name>user</principal-name>
        </security-role-mapping> 
    

    没有默认主体映射的记录错误:  1.没有Principal映射到Role [user]。  2.没有Principal映射到Role [admin]。


    (2)基于数据库的身份验证:

    Realm将上述领域更改为web.xml中的jdbcRealm

    • 1)m-n(用户和组表之间的多对多关系)

      SEC1111,无法为JDBC领域用户[tamas]加载组。

    • 2)1-n相同(用户和组表之间的一对多关系)

      SEC1111,无法为JDBC领域用户[tamas]加载组。

    • 3)与用户名和密码相同的表中的组名

      SEC1111,无法为JDBC领域用户[tamas]加载组。

    领域配置: (我也尝试离开&#34;分配组&#34;空白或填写&#34;默认&#34;但结果是相同的。)

    Image had to be omitted, summary:
    JAAS context: jdbcRealm
    JNDI: jdbc/securityDataSource
    User Table: TBLUSERS
    User Name Column: USERNAME
    Password Column: PASSWORD
    Group Table: TBLGROUPS
    Group Name Column: GROUPNAME
    Assign Groups: default
    Digest Algorithm: none 
    

    m-n关系的DB ER图:

    图片必须省略,但作为补偿:-)你找到下面的SQL脚本。

    SQL Script:
    SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
    SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
    SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
    
    CREATE SCHEMA IF NOT EXISTS `jdbcrealm` ;
    USE `jdbcrealm` ;
    
    -- -----------------------------------------------------
    -- Table `jdbcrealm`.`TBLUSERS`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `jdbcrealm`.`TBLUSERS` ;
    CREATE  TABLE IF NOT EXISTS `jdbcrealm`.`TBLUSERS` (
      `USERID` INT NOT NULL AUTO_INCREMENT ,
      `USERNAME` VARCHAR(30) NOT NULL ,
      `PASSWORD` VARCHAR(45) NOT NULL ,
      UNIQUE INDEX `USERNAME_UNIQUE` (`USERNAME` ASC) ,
      PRIMARY KEY (`USERID`) )
    
    ENGINE = InnoDB;
    
    -- -----------------------------------------------------
    -- Table `jdbcrealm`.`TBLGROUPS`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `jdbcrealm`.`TBLGROUPS` ;
    CREATE  TABLE IF NOT EXISTS `jdbcrealm`.`TBLGROUPS` (
      `GROUPID` INT NOT NULL AUTO_INCREMENT ,
      `GROUPNAME` VARCHAR(30) NOT NULL ,
      PRIMARY KEY (`GROUPID`) )
    
    ENGINE = InnoDB;
    
    -- -----------------------------------------------------
    -- Table `jdbcrealm`.`USERS_GROUPS`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `jdbcrealm`.`USERS_GROUPS` ;
    CREATE  TABLE IF NOT EXISTS `jdbcrealm`.`USERS_GROUPS` (
      `USER_USERID` INT NOT NULL ,
      `GROUP_GROUPID` INT NOT NULL ,
      PRIMARY KEY (`USER_USERID`, `GROUP_GROUPID`) ,
    
      INDEX `fk_USER_has_GROUP_GROUP1` (`GROUP_GROUPID` ASC) ,
      INDEX `fk_USER_has_GROUP_USER` (`USER_USERID` ASC) ,
      CONSTRAINT `fk_USER_has_GROUP_USER`
        FOREIGN KEY (`USER_USERID` )
        REFERENCES `jdbcrealm`.`TBLUSERS` (`USERID` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_USER_has_GROUP_GROUP1`
        FOREIGN KEY (`GROUP_GROUPID` )
        REFERENCES `jdbcrealm`.`TBLGROUPS` (`GROUPID` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    
    ENGINE = InnoDB;
    
    SET SQL_MODE=@OLD_SQL_MODE;
    SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
    SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
    

    我在这里复制一些关于这个主题的有趣的Google搜索链接,这些链接对我有帮助。最初,我跟着第二个。也许其他人也会觉得它们很有用。

    感谢您阅读目前为止。祝福,

    的Tamas



    第2部分 感谢您的回复。我创建了2个具有一对多关系的新表用户和组。在领域配置页面上,我设置了用户名,密码和组的表名和列。马特的评论也与链接一致(见下文我不能在这里发布)

      

    [...]   这里有趣的部分是我使用的用户表和组表   v_user_role作为属性的值。 v_user_role是一个数据库   包含用户和组信息的视图。我之所以这样   没有直接使用users表是因为glassfish认为是这样   user表和group表都包含一个包含的列   用户名,这将导致重复的数据。   [...]

    -- -----------------------------------------------------
    -- Table `jdbcrealm`.`user`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `jdbcrealm`.`user` ;
    CREATE  TABLE IF NOT EXISTS `jdbcrealm`.`user` (
      `userid` VARCHAR(30) NOT NULL ,
      `password` VARCHAR(45) NOT NULL ,
      PRIMARY KEY (`userid`) )
    ENGINE = InnoDB;
    
    -- -----------------------------------------------------
    -- Table `jdbcrealm`.`group`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `jdbcrealm`.`group` ;
    CREATE  TABLE IF NOT EXISTS `jdbcrealm`.`group` (
      `groupid` VARCHAR(30) NOT NULL ,
      `userid` VARCHAR(30) NOT NULL ,
      INDEX `fk_group_user1` (`userid` ASC) ,
      CONSTRAINT `fk_group_user1`
        FOREIGN KEY (`userid` )
        REFERENCES `jdbcrealm`.`user` (`userid` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;
    

    出现同样的错误。我还试图以一种方式将主键放在组表中的列groupid上,但我从问题的角度来看没有任何变化。同样有趣的是,我试图对1个用户名,pwds,组所在的表做同样的错误。



    迈向解决方案和解决方案

    Matt的评论帮助很多,感谢这篇精彩的帖子。总之,在我编写与基于数据库的身份验证相关的问题之初,很明显无法加载用户组。这由server.log中的错误消息指示。

    然而,我的怀疑转向了表格及其列名之间的联系。然而,在简化了用户组实体的数据模型之后,我无法解释为什么即使使用包含user,pwd和group的简单表也无法工作。我继续朝着这个方向进行调查。我假设列名也可以影响这一点。当我应用Matt的配置时,&#34;无法加载组&#34;消息从server.log消失,但现象保持不变。因此我假设这些组已经可以加载但是也存在不同的问题。然后我接受了Matt的配置并开始逐步更改列名称以接近原始配置但是&#34;无法加载组&#34;消息没有出现在日志中。当我使用我的原始设置重现案例并且日志消息不存在时,我知道它以某种方式被关闭的日志记录出了问题。所以我开始调查整个配置。

    当我查看已部署的应用程序时,我选择了部署描述符并将它们加载到glassfish控制台上。 web.xml很好,它有我写的相同内容,但 glassfish-web.xml有一个完全不同的内容!它的生成好像我没有glassfish-web.xml。然后我注意到我的glassfish-web.xml没有放在WEB-INF目录中。我把它移到那里并做了一个&#34;清洁所有,建立&#34;并部署了该应用程序。之后我回到db视图,它以多对多的关系表示TBLUSERS和TBLGROUPS之间的数据。我最喜欢这个解决方案,因为它从数据的角度展示了最清晰的图片。我在领域配置页面上设置了适当的列。我用两个用户测试了它&#34; tamas&#34;和&#34; arpi&#34;。 &#34;塔玛斯&#34;同时添加到用户和管理员组&#34; arpi&#34;已添加到用户组。角色和用户组之间的映射位于glassfish-web.xml中。访问了&#34; tamas&#34; &#34; arpi&#34;同时提供用户和管理资源只能访问用户资源。

    感谢您的帮助。的Tamas

1 个答案:

答案 0 :(得分:7)

从第一眼看,我会发现你的表名列。

根据我自己的经验,我记住用户表中的用户列需要与USER_GROUPS表中的用户列具有完全相同的名称。匹配由列名完成。

因此,您的USER_GROUPS表需要一个与USERNAME表中的用户名匹配的列TBLUSERS

请注意,您必须为此更改表关系。

可能有十几种其他原因,但你可以尝试一下。

这是我的本地配置:

CREATE TABLE `user` (
  `LOGIN` varchar(32) NOT NULL,
  `password` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`LOGIN`)
)

CREATE TABLE `group` (
  `IDGROUP` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`IDGROUP`)
)

CREATE TABLE `group_has_user` (
  `IDGROUP` int(11) NOT NULL,
  `LOGIN` varchar(32) NOT NULL,
  PRIMARY KEY (`IDGROUP`,`LOGIN`),
  KEY `fk_group_has_user_user1` (`LOGIN`),
  CONSTRAINT `fk_group_has_user_user1` FOREIGN KEY (`LOGIN`) 
     REFERENCES `user` (`LOGIN`) 
     ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_group_has_user_group1` FOREIGN KEY (`IDGROUP`) 
     REFERENCES `group` (`IDGROUP`) 
     ON DELETE NO ACTION ON UPDATE NO ACTION
)

在GF管理控制台中使用以下设置:

enter image description here

这是我从sun-web.xml(现在是glassfish-web.xml)的安全角色映射:

<security-role-mapping>
    <role-name>user</role-name>
    <group-name>1</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>sponsor</role-name>
    <group-name>2</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>admin</role-name>
  <group-name>3</group-name>
</security-role-mapping>

我已经在login-config下面的web.xml中定义了以下安全角色:

<security-role>
   <description/>
   <role-name>user</role-name>
</security-role>
<security-role>
   <description/>
   <role-name>sponsor</role-name>
</security-role>
<security-role>
   <description/>
   <role-name>admin</role-name>
</security-role>