添加用户数据库资源链接后,Tomcat 身份验证失败



问题:

添加 Tomcat 资源链接后<ResourceLink name="UserDatabase" global="UserDatabase" type="org.apache.catalina.UserDatabase"/>我的身份验证已损坏。我可以登录并执行 REST 调用,从 tomcat-users.xml 获取所有用户。然后我只是重新加载页面,出现 403 - 禁止错误。

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

代码/错误

(查看 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

网络.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>

上下文.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>

雄猫用户.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;
}

我在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);
}

这看起来像是雄猫roles问题。您可以使用以下配置来允许所有角色。

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

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

最新更新