【问题标题】:Tomcat authentication failed after adding UserDatabase ResourceLink添加 UserDatabase ResourceLink 后 Tomcat 身份验证失败
【发布时间】:2020-09-23 10:45:44
【问题描述】:

问题:

在我添加 Tomcat ResourceLink <ResourceLink name="UserDatabase" global="UserDatabase" type="org.apache.catalina.UserDatabase"/> 后,我的身份验证被破坏。我可以登录并执行 REST CALL,从 tomcat-users.xml 中获取所有用户。然后我重新加载页面,出现 403 - Forbidden 错误。

我有两个 Web 应用程序。一个是从数据库(后端)获取数据的 REST API,另一个 Web 应用程序用于管理数据库(前端)。
所以我为我的前端应用程序添加了一个 FORM 身份验证,并为我的后端添加了一个 BASIC 身份验证。用户存储在 tomcat-users.xml 文件中 -> 一切正常
现在我想用前端/后端以编程方式编辑 tomcat 用户,我发现了这个 how to programmatically add users to tomcat UserDatabaseRealm?
我将链接中的代码添加到我的 REST API 中,然后调用 URL /api/admin/tomcat/user 我得到了所有用户和用户角色。但是在此页面上一次调用后,我总是收到 403 - Forbidden 错误!
如果我不执行 REST CALL 或仅删除 ResourceLink,则不会发生问题。

代码/错误

(看Tomcat Logs的最后两行。为什么他第一次找到了角色,而第二次没有找到?)

Tomcat 日志:

成功登录/第一次调用页面后的日志:

[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke Security checking request GET /es_admin/admin/setting.jsp
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke We have cached auth type FORM for principal GenericPrincipal[admin(CR8000,SOLIDWORKS,admin,)]
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Adminstrative Pages]' against GET /admin/setting.jsp --> true
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[User Pages]' against GET /admin/setting.jsp --> false
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Adminstrative Pages]' against GET /admin/setting.jsp --> true
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[User Pages]' against GET /admin/setting.jsp --> false
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling hasUserDataPermission()
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.hasUserDataPermission   User data constraint has no restrictions
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling authenticate()
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.checkForCachedAuthentication Bereits authentifiziert [admin]
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling accessControl()
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.hasResourcePermission   Checking roles GenericPrincipal[admin(CR8000,SOLIDWORKS,admin,)]
[http-nio-8080-exec-8] org.apache.catalina.realm.RealmBase.hasResourcePermission Role found:  admin
[http-nio-8080-exec-8] org.apache.catalina.authenticator.AuthenticatorBase.invoke Successfully passed all security constraints

我重新加载页面或只是切换到另一个页面后的日志:

[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke Security checking request GET /es_admin/admin/setting.jsp
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke We have cached auth type FORM for principal GenericPrincipal[admin(CR8000,SOLIDWORKS,admin,)]
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[User Pages]' against GET /admin/setting.jsp --> false
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Adminstrative Pages]' against GET /admin/setting.jsp --> true
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[User Pages]' against GET /admin/setting.jsp --> false
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Adminstrative Pages]' against GET /admin/setting.jsp --> true
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling hasUserDataPermission()
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.hasUserDataPermission   User data constraint has no restrictions
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling authenticate()
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.checkForCachedAuthentication Bereits authentifiziert [admin]
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke Calling accessControl()
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.hasResourcePermission   Checking roles GenericPrincipal[admin(CR8000,SOLIDWORKS,admin,)]
[http-nio-8080-exec-15] org.apache.catalina.realm.RealmBase.hasResourcePermission No role found:  admin
[http-nio-8080-exec-15] org.apache.catalina.authenticator.AuthenticatorBase.invoke Failed accessControl() test

web.xml - 前端

 <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>frontend</display-name>
   <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
   </welcome-file-list>

    <!--Defines Security Constraint -->
    <security-constraint>
        <display-name>frontend admin</display-name>
        <web-resource-collection>
            <web-resource-name>Adminstrative Pages</web-resource-name>
            <description/>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <display-name>frontend user</display-name>
        <web-resource-collection>
            <web-resource-name>User Pages</web-resource-name>
            <description/>
            <url-pattern>/user/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>SOLIDWORKS</role-name>
        </auth-constraint>
        <auth-constraint>
            <description/>
            <role-name>CR8000</role-name>
        </auth-constraint>
    </security-constraint>

<!--Defines Login Config -->
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>file</realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>

<!--Defines Security Role -->
    <security-role>
        <description/>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <description/>
        <role-name>SOLIDWORKS</role-name>
    </security-role>
    <security-role>
        <description/>
        <role-name>CR8000</role-name>
    </security-role>
</web-app>

context.xml

<Context>
    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <ResourceLink name="UserDatabase" global="UserDatabase" type="org.apache.catalina.UserDatabase" />

</Context>

tomcat-users.xml

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">

<role rolename="admin"/>
<role rolename="CR8000"/>
<role rolename="SOLIDWORKS"/>

<user username="admin" password="password" roles="admin,CR8000,SOLIDWORKS"/>
<user username="testSolid" password="password" roles="SOLIDWORKS"/>
<user username="testZuken" password="password" roles="CR8000"/>
</tomcat-users>

领域配置

<Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>

在这个方法之后错误来了

    @GET
    @Path("/tomcat/user")
    @Produces(MediaType.APPLICATION_JSON)
    public ArrayList<TomcatUser> getTomcatUser() {

        getLogWriter().writeLog("GET call on /tomcat/user");
        ArrayList<TomcatUser> tomcatUsers = new ArrayList<TomcatUser>();

        try {
            UserDatabase ud =  (UserDatabase) new InitialContext().lookup("java:comp/env/UserDatabase");

            ud.open();

            Iterator<org.apache.catalina.User> iteratorUsers = ud.getUsers();

            while (iteratorUsers.hasNext()) {
                org.apache.catalina.User user = iteratorUsers.next();

                TomcatUser tmpTomcatUser = new TomcatUser();
                String username = user.getUsername();

                Iterator<Role> iteratorRoles = user.getRoles();
                ArrayList<Role> roles = new ArrayList<Role>();

                // Change from Iterator to ArrayList
                iteratorRoles.forEachRemaining(roles::add);

                ArrayList<String> strRoles = new ArrayList<String>();

                for (int x = 0; x < roles.size(); x++) {
                    strRoles.add(roles.get(x).getRolename());
                }

                tmpTomcatUser.setUsername(username);
                tmpTomcatUser.setRoles(strRoles);

                tomcatUsers.add(tmpTomcatUser);
                tmpTomcatUser = null;
            }

            ud.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return tomcatUsers;
    }

【问题讨论】:

  • @Pandurang - tomcat_roles 表中的角色名称和 web.xml 中的角色名称相同。我在我的问题中添加了tomcat-users.xml
  • 能否在web.xml文件中使用&lt;role-name&gt;*&lt;/role-name&gt;。重启tomcat服务器并测试。
  • @Pandurang - 成功了! 问题解决了! ...但是为什么,我怎样才能用我的角色来解决它?只有具有管理员角色的用户才能访问该页面

标签: jsp tomcat realm tomcat9


【解决方案1】:

这看起来像 tomcat 中的roles 问题。您可以使用以下配置来允许所有角色。

<role-name>*</role-name>

根据问题的默认设置,tomcat-user.xml 文件在基本身份验证中运行良好。使用how to programmatically add users to tomcat UserDatabaseRealm? 后,您面临角色问题。这是真的吗?如果是,那么我认为您还需要以编程方式传递角色。

【讨论】:

  • 添加了领域配置,tomcat_roles 是指tomcat-users.xml,对吧?
  • 根据问题的默认设置,tomcat-user.xml 文件与Basic authentication 一起工作正常。使用how to programmatically add users to tomcat UserDatabaseRealm? 后,您面临角色问题。这是真的吗?如果是,那么我认为您还需要以编程方式传递角色。
  • 是的,没错。在我添加我的 Servlet 调用以获取所有用户和角色后,问题出现了。我在阅读tomcat_users 的地方添加了我的Java 方法。我以编程方式尝试角色并提供反馈
  • 您需要专注于您的 servlet。 tomcat 配置看起来不错。
  • 你是对的,问题是servlet,谢谢你的支持!
【解决方案2】:

我在我的servlet中发现了两个问题来解决这个问题:

  1. 我从我的UserDatabase 中删除了方法调用.open()
  2. 我必须返回一个字符串而不是TomcatUser 对象。为了返回一个字符串,我使用 Gson 将我的对象格式化为 JSON 字符串。

所以这是我最终的 servlet 方法:

@GET
@Path("/tomcat/user")
@Produces(MediaType.APPLICATION_JSON)
public String getTomcatUser() {

    getLogWriter().writeLog("GET call on /tomcat/user");
    ArrayList<TomcatUser> tomcatUsers = new ArrayList<TomcatUser>();

    try {
        UserDatabase ud =  (UserDatabase) new InitialContext().lookup("java:comp/env/UserDatabase");

        Iterator<org.apache.catalina.User> iteratorUsers = ud.getUsers();

        while (iteratorUsers.hasNext()) {

            org.apache.catalina.User user = iteratorUsers.next();
            System.out.println(user.getUsername());

            TomcatUser tmpTomcatUser = new TomcatUser();
            String username = user.getUsername();

            Iterator<Role> iteratorRoles = user.getRoles();
            ArrayList<String> strRoles = new ArrayList<String>();

            while (iteratorRoles.hasNext()) {
                Role role = iteratorRoles.next();
                strRoles.add(role.getRolename());
            }

            tmpTomcatUser.setUsername(username);
            tmpTomcatUser.setRoles(strRoles);

            tomcatUsers.add(tmpTomcatUser);
            tmpTomcatUser = null;
        }


    } catch (Exception e) {
        e.printStackTrace();
    }

    return new Gson().toJson(tomcatUsers);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 2017-11-27
    相关资源
    最近更新 更多