设为首页 收藏本站
查看: 861|回复: 0

[经验分享] tomcat realm-java之condition-运维网 博客

[复制链接]

尚未签到

发表于 2018-12-1 07:12:38 | 显示全部楼层 |阅读模式
Realm 配置
快速入门
  本文档介绍了如何借助一个“数据库”来配置 Tomcat ,从而实现容器管理安全性。所要连接的这种数据库含有用户名、密码以及用户角色。你只需知道的是,如果使用的 Web 应用含有一个或多个  元素, 元素定义了用户验证的必需细节信息。如果你不打算使用这些功能,则可以忽略这篇文档。
  关于容器管理安全性的基础知识,可参考 该文档。
概述
什么是 Realm
  Realm(安全域)其实就是一个存储用户名和密码的“数据库”再加上一个枚举列表。“数据库”中的用户名和密码是用来验证 Web 应用(或 Web 应用集合)用户合法性的,而每一合法用户所对应的角色存储在枚举列表中。可以把这些角色看成是类似 UNIX 系统中的 group(分组),因为只有能够拥有特定角色的用户才能访问特定的 Web 应用资源(而不是通过对用户名列表进行枚举适配)。特定用户的用户名下可以配置多个角色。
  虽然 Servlet 规范描述了一个可移植机制,使应用可以在 web.xml 部署描述符中声明它们的安全需求,但却没有提供一种可移植 API 来定义出 Servlet 容器与相应用户及角色信息的接口。然而,在很多情况下,非常适于将 Servlet 容器与一些已有的验证数据库或者生产环境中已存在的机制“连接”起来。因此,Tomcat 定义了一个 Java 接口(org.apache.catalina.Realm),通过“插入”组件来建立连接。提供了 6 种标准插件,支持与各种验证信息源的连接:

  •   JDBCRealm——通过 JDBC 驱动器来访问保存在关系型数据库中的验证信息。
  •   DataSourceRealm——访问保存在关系型数据库中的验证信息。
  •   JNDIRealm——访问保存在 LDAP 目录服务器中的验证信息。
  •   UserDatabaseRealm——访问存储在一个 UserDatabase JNDI 数据源中的认证信息,通常依赖一个 XML 文档(conf/tomcat-users.xml)。
  •   MemoryRealm——访问存储在一个内存中对象集合中的认证信息,通过 XML 文档初始化(conf/tomcat-users.xml)。
  •   JAASRealm——通过 Java 认证与授权服务(JAAS)架构来获取认证信息。
  另外,还可以编写自定义 Realm 实现,将其整合到 Tomcat 中,只需这样做:

  •   实现 org.apache.catalina.Realm 接口。
  •   将编译好的 realm 放到 $CATALINA_HOME/lib 中。
  •   声明自定义 realm,具体方法详见“配置 Realm”一节。
  •   在 MBeans 描述符文件中声明自定义realm。
配置 Realm
  在详细介绍标准 Realm 实现之前,简要了解 Realm 的配置方式是很关键的一步。大体来说,就是需要在conf/server.xml 配置文件中添加一个 XML 元素,如下所示:

   可以嵌入以下任何一种 Container 元素中。Realm 元素的位置至关重要,它会对 Realm 的“范围”(比如说哪个 Web 应用能够共享同一验证信息)有直接的影响。

  •    元素 内嵌入该元素中的这种 Realm 元素可以被所有虚拟主机上的所有 Web 应用所共享,除非该 Realm 元素被内嵌入下属  或  元素的 Realm 元素所覆盖。
  •    元素 内嵌入该元素中的这种 Realm 元素可以被这一虚拟主机上的所有 Web 应用所共享。除非该 Realm 元素被内嵌入下属  元素的 Realm 元素所覆盖。
  •    元素 内嵌入该元素中的这种 Realm 元素只能被这一 Web 应用所使用。
常用特性
摘要式密码
  对于每种标准 Realm 实现来说,用户的密码默认都是以明文方式保存的。在很多情况下,这种方式都非常糟糕,即使是一般的用户也能收集到足够的验证信息,从而以其他用户的信息成功登录。为了避免这种情况的发生,标准 Realm 实现支持一种对用户密码进行摘要式处理的机制,它能以无法轻易破解的形式对存储的密码进行加密处理,同时保证Realm 实现仍能使用这种加密后的密码进行验证。
  在标准的 Realm 验证时,会将存储的密码与用户所提供的密码进行比对,这时,我们可以通过指定  元素中的 digest 属性来选择摘要式密码。该属性值必须是一种java.security.MessageDigest 类所支持的摘要式算法(SHA、MD2、或 MD5)。当你选择该属性值时,存储在 Realm 中的密码内容必须是明文格式,随后它将被你所指定的算法进行摘要式加密。
  在调用 Realm 的 authenticate() 方法后,用户所提供的明文密码同样也会利用上述你所指定的加密算法进行加密,加密结果与 Realm 的返回值相比较。如果两者相等,则表明原始密码的明文形式更用户所提供的密码完全等同,因此该用户身份验证成功。
  可以采用以下两种比较便利的方法来计算明文密码的摘要值:

  •   如果应用需要动态计算摘要式密码,调用 org.apache.catalina.realm.RealmBase 类的静态 Digest() 方法,传入明文密码和摘要式算法名称及字符编码方案。该方法返回摘要式密码。
  •   如果想执行命令行工具来计算摘要式密码,只需执行:
      CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} {cleartext-password}
      标准输出将返回明文密码的摘要式形式。
  如果使用 DIGEST 验证的摘要式密码,用来生成摘要密码的明文密码则将有所不同,而且必须使用一次不加盐的 MD5 算法。对应到上面的范例,那就是必须把 {cleartext-password} 替换成 {username}:{realm}:{cleartext-password}。再比如说,在一个开发环境中,可能采用这种形式:testUser:Authentication required:testPassword。{realm} 的值取自 Web 应用  的  元素。如果没有在 web.xml 中指定,则使用默认的Authentication required。
  若要使用非平台默认编码的用户名和(或)密码,则命令如下:
  CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} -e {encoding} {input}
  但需要注意的是,一定要确保输入正确地传入摘要。摘要返回 {input}:{digest}。如果输入在返回时出现损坏,摘要则将无效。
  摘要的输出格式为 {salt}${iterations}${digest}。如果盐的长度为 0,迭代次数为 1,则输出将简化为 {digest}。
  CATALINA_HOME/bin/digest.[bat|sh] 的完整格式如下:
CATALINA_HOME/bin/digest.[bat|sh] [-a ] [-e ]  
        [-i ] [-s ] [-k ]
  
        [-h ]

  •   -a 用来生成存储凭证的算法。如未指定,将使用凭证处理器(CredentialHandler)的默认值,如果认证处理器和算法均未指定,则使用默认值 SHA-512。
  •   -e 指定用于任何必要的字节与字符间转换的字符编码方案。如未指定,使用系统默认的字符编码方案 Charset#defaultCharset()。
  •   -i 生成存储的凭证时所使用的迭代次数。如未指定,使用 CredentialHandler 的默认值。
  •   -s 生成并存储到认证中的盐的长度(字节)。如未指定,使用 CredentialHandler 的默认值。
  •   -k (生成凭证时,如果随带创建了)键的长度(位)。如未指定,则使用 CredentialHandler 的默认值
  •   -h CredentialHandler 使用的完整类名。如未指定,则轮流使用内建的凭证处理器(MessageDigestCredentialHandler,然后是 SecretKeyCredentialHandler),将使用第一个接受指定算法的凭证处理器。
范例应用
  Tomcat 自带的范例应用中包含一个受到安全限制保护的区域,使用表单式登录方式。为了访问它,在你的浏览器地址栏中输入 http://localhost:8080/examples/jsp/security/protected/,并使用 Realm 配置文档中。
范例
  下面这个 SQL 脚本范例创建了我们所需的表(根据你所用的数据库,可以相应修改其中的语法)。
create table users (  
  user_name         varchar(15) not null primary key,
  
  user_pass         varchar(15) not null
  
);
  

  
create table user_roles (
  
  user_name         varchar(15) not null,
  
  role_name         varchar(15) not null,
  
  primary key (user_name, role_name)
  
);
  Realm 元素包含在默认的 $CATALINA_BASE/conf/server.xml 文件中(被注释掉了)。在下面的范例中,有一个名为 authority 的数据库,它包含上述创建的表,通过用户名“dbuser”和密码“dbpass”进行访问。

特别注意事项
  JDBCRealm 必须遵循以下规则:

  •   当用户首次访问一个受保护资源时,Tomcat 会调用这一 Realm 的 authenticate() 方法,从而使任何对数据库的即时修改(新用户、密码或角色改变,等等)都能立即生效。
  •   一旦用户认证成功,在登录后,该用户(及其相应角色)就将缓存在 Tomcat 中。(对于以表单形式的认证,这意味着直到会话超时或者无效才会过期;对于基本形式的验证,意味着直到用户关闭浏览器才会过期。)在会话序列化期间不会保存或重置缓存的用户。对已认证用户的数据库信息进行的任何改动都不会生效,直到该用户下次登录。
  •   应用负责管理users(用户表)和user roles(用户角色表)中的信息。Tomcat 没有提供任何内置功能来维护这两种表。
DataSourceRealm
简介
  DataSourceRealm 是 Tomcat Realm 接口的一种实现,它通过一个 JNDI 命名的 JDBC 数据源在关系型数据库中查找用户。只要数据库结构符合下列要求,你可以通过大量的配置来灵活地修改现有的表与列名。

  •   必须有一张用户表(users table)。它包含着一个由 Realm 所能识别的所有合法用户所构成的行。
  •   用户表必须至少包含两列(当然,如果现有应用确实需要,则同样也可以包含更多的列):

    •   用户名。当用户登录时,能被 Tomcat 识别的用户名。
    •   密码。当用户登录时,能被 Tomcat 所识别的密码。该列中的值可能是明文,也可能是摘要式密码,稍后详述。

  •   必须有一张用户角色表(user roles table)。该表包含一个角色行,包含着可能指定给特定用户的每个合法角色。一个用户可以没有角色,也可以有一个或多个角色,这都是合法的。
  •   用户角色表 至少应包含两列(如果现有应用确实需要,则也可以包含更多的列):

    •   用户名。Tomcat 所能识别的用户名(与用户表中指定的值相同)。
    •   用户所对应的合法角色名。

快速入门
  为了设置 Tomcat 从而使用 DataSourceRealm,需要执行以下步骤:

  •   在数据库中创建符合上述规范的表与列。
  •   配置一个 Tomcat 使用的数据库用户名与密码,并且至少有只读权限(Tomcat 永远都不会去修改那些表中的数据)。
  •   为数据库配置一个 JNDI 命名的 JDBC DataSource。详情可参考Realm 配置文档中。
    范例
      在目录服务器上创建适合的模式超出了本文档的讲解范围,因为这是跟每个目录服务器的实现密切相关的。在下面的实例中,我们将假定使用的是 OpenLDAP 目录服务器的一个分发版(2.0.11 版或更新版本,可从http://www.openldap.org处下载)。假设 slapd.conf 文件包含下列设置(除了其他设置之外)。
    database ldbm  
    suffix dc="mycompany",dc="com"
      
    rootdn "cn=Manager,dc=mycompany,dc=com"
      
    rootpw secret
      我们还假定 connectionURL,使目录服务器与 Tomcat 运行在同一台机器上。要想了解如何配置及使用 JNDI LDAP 提供者的详细信息,请参看 http://docs.oracle.com/javase/7/docs/technotes/guides/jndi/index.html。
      接下来,假定利用如下所示的元素(以 LDIF 格式)来填充目录服务器。
    # Define top-level entry  
    dn: dc=mycompany,dc=com
      
    objectClass: dcObject
      
    dc:mycompany
      

      
    # Define an entry to contain people
      
    # searches for users are based on this entry
      
    dn: ou=people,dc=mycompany,dc=com
      
    objectClass: organizationalUnit
      
    ou: people
      

      
    # Define a user entry for Janet Jones
      
    dn: uid=jjones,ou=people,dc=mycompany,dc=com
      
    objectClass: inetOrgPerson
      
    uid: jjones
      
    sn: jones
      
    cn: janet jones
      
    mail: j.jones@mycompany.com
      
    userPassword: janet
      

      
    # Define a user entry for Fred Bloggs
      
    dn: uid=fbloggs,ou=people,dc=mycompany,dc=com
      
    objectClass: inetOrgPerson
      
    uid: fbloggs
      
    sn: bloggs
      
    cn: fred bloggs
      
    mail: f.bloggs@mycompany.com
      
    userPassword: fred
      

      
    # Define an entry to contain LDAP groups
      
    # searches for roles are based on this entry
      
    dn: ou=groups,dc=mycompany,dc=com
      
    objectClass: organizationalUnit
      
    ou: groups
      

      
    # Define an entry for the "tomcat" role
      
    dn: cn=tomcat,ou=groups,dc=mycompany,dc=com
      
    objectClass: groupOfUniqueNames
      
    cn: tomcat
      
    uniqueMember: uid=jjones,ou=people,dc=mycompany,dc=com
      
    uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
      

      
    # Define an entry for the "role1" role
      
    dn: cn=role1,ou=groups,dc=mycompany,dc=com
      
    objectClass: groupOfUniqueNames
      
    cn: role1
      
    uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
      OpenLDAP 服务器。假定用户使用他们的 uid(比如说 jjones)登录应用,匿名连接已经足够可以搜索目录并获取角色信息了:

      利用这种配置,通过在 userPattern 替换用户名,realm 能够确定用户的 DN,然后利用这个 DN 和取自用户的密码将用户绑定到目录中,从而验证用户身份,然后搜索整个目录服务器来找寻用户角色。

      现在假定希望用户输入电子邮件地址(而不是用户>  另外,假设除了分组项之外,你还想用用户项的属性来保存角色,那么在这种情况下,Janet Jones 对应的项可能如下所示:
    dn: uid=jjones,ou=people,dc=mycompany,dc=com  
    objectClass: inetOrgPerson
      
    uid: jjones
      
    sn: jones
      
    cn: janet jones
      
    mail: j.jones@mycompany.com
      
    memberOf: role2
      
    memberOf: role3
      
    userPassword: janet
      这个 realm 配置必须满足以下新要求:

      当 Janet Jones 用她的电子邮件 j.jones@mycompany.com 登录时,realm 会搜索目录,寻找带有该电邮值的唯一项,并尝试利用给定密码来绑定到目录:uid=jjones,ou=people,dc=mycompany,dc=com。如果验证成功,该用户将被赋予以下三个角色:"role2" 与 "role3",她的目录项中的 memberOf 属性值;"tomcat",她作为成员存在的唯一分组项中的 cn 属性值。
      最后,为了验证用户,我们必须从目录中获取密码并在 realm 中执行本地比对,将 realm 按照如下方式来配置:

      但是,正如之前所讨论的那样,往往应该优先考虑默认的绑定模式。
    特别注意事项
      使用 JNDIRealm 需要遵循以下规则:
    UserDatabaseRealm
      UserDatabaseRealm 是 Tomcat Realm 接口的一种实现,使用 JNDI 资源来存储用户信息。默认,JNDI 资源是通过一个 XML 文件来提供支持的。它并不是针对大规模生产环境用途而设计的。在启动时,UserDatabaseRealm 会从一个 XML 文档中加载所有用户以及他们角色的信息(该 XML 文档默认位于 $CATALINA_BASE/conf/tomcat-users.xml。)用户、密码以及相应角色通常可利用 JMX 进行动态编辑,更改结果会加以保存并立刻反映在 XML 文档中。
    Realm 元素属性
      跟之前讨论的一样,为了配置 UserDatabaseRealm,需要在 $CATALINA_BASE/conf/server.xml 中创建  元素。关于 UserDatabaseRealm 中的属性定义可参看 Realm 配置文档。
    用户文件格式
      用户文件包含下列属性。默认情况下,conf/tomcat-users.xml 必须是一个 XML 文件,并且带有一个根元素:。每一个有效用户都有一个内嵌在根元素中的  元素。
    特别注意事项
      使用 MemoryRealm 需要注意以下规则:
    JAASRealm
    简介
      JAASRealm 是 Tomcat 的 Realm 接口的一种实现,通过 Java Authentication & Authorization Service(JAAS,Java身份验证与授权服务)架构来实现对用户身份的验证。JAAS 架构现已加入到标准的 Java SE API 中。
      通过 JAASRealm,开发者实际上可以将任何安全的 Realm 与 Tomcat 的 CMA 一起组合使用。
      JAASRealm 是 Tomcat 针对基于 JAAS 的 J2EE 1.4 的 J2EE 认证框架的原型实现,基于 JAAS 认证教程 与 JAAS LoginConfig 文件)。将其位置指定给 JVM,从而便于 Tomcat 明确它的位置。例如,设置如下环境变量:
      JAVA_OPTS=$JAVA_OPTS -Djava.security.auth.login.config==$CATALINA_BASE/conf/jaas.config


  •   当 Tomcat 首次启动时,它会从用户文件中加载所有已定义的用户及其相关信息。假如对该用户文件中的数据进行修改,则只有重启 Tomcat 后才能生效。
  •   当用户首次访问一个受保护资源时,Tomcat 会调用这一 Realm 的 authenticate() 方法。
  •   一旦用户认证成功,在登录后,该用户(及其相应角色)就将缓存在 Tomcat 中。(对于以表单形式的认证,这意味着直到会话超时或者无效才会过期;对于基本形式的验证,意味着直到用户关闭浏览器才会过期。)在会话序列化期间不会保存或重置缓存的用户。对已认证用户的数据库信息进行的任何改动都不会生效,直到该用户下次登录。
  •   应用负责管理users(用户表)和user roles(用户角色表)中的信息。Tomcat 没有提供任何内置功能来维护这两种表。


  •   name 用户登录所用的用户名。
  •   password 用户登录所用的密码。如果  元素中没有设置 digest 属性,则采用明文密码,否则就设置为摘要式密码,如之前讨论的那样。
  •   roles 以逗号分隔的用户角色名列表。


  •   当用户首次访问一个受保护资源时,Tomcat 会调用这一 Realm 的 authenticate() 方法,从而使任何对数据库的即时修改(新用户、密码或角色改变,等等)都能立即生效。
  •   一旦用户认证成功,在登录后,该用户(及其相应角色)就将缓存在 Tomcat 中。(对于以表单形式的认证,这意味着直到会话超时或者无效才会过期;对于基本形式的验证,意味着直到用户关闭浏览器才会过期。)在会话序列化期间不会保存或重置缓存的用户。对已认证用户的数据库信息进行的任何改动都不会生效,直到该用户下次登录。
  •   应用负责管理users(用户表)和user roles(用户角色表)中的信息。Tomcat 没有提供任何内置功能来维护这两种表。
为了保护一些资源,在 web.xml 中配置安全限制。在 server.xml 中配置 JAASRealm 模块。重启 Tomcat(如果它正在运行)。Realm 元素属性
  在上述步骤中,为了配置步骤 6 以上的 JAASRealm,需要创建一个  元素,并将其内嵌在  元素中的 $CATALINA_BASE/conf/server.xml 文件内。关于 JAASRealm 中的属性定义可参看 Realm 配置文档。
范例
  下面是 server.xml 中的一段代码,为 UserDatabaseRealm 添加了锁定功能。
  
   
  




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-641730-1-1.html 上篇帖子: tomcat 配置文件详解 下篇帖子: 注册Tomcat到Window Service服务
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表