How to configure kerberos on Tomcat/linux server?

早过忘川 提交于 2019-12-23 00:46:26

问题


I'm trying to setup kerberos authentication in a Java web-app running in a Tomcat on Linux. I'm using the spring security kerberos extension. I'm using:

  • jdk 1.7u75
  • spring-security-kerberos 1.0.0.RELEASE
  • MS Active Directory

On my local development machine (windows) everything runs fine. But after deploying the app to a linux machine authentication is no longer working. I strongly suspect that something is wrong with my Kerberos configuration :

[libdefaults]
  default_realm = INT.MYCOMPANY.DE
  ccache_type=4
  kdc_tymesync=1
  forwardable=true
  proxiable=true

[realms]
  INT.MYCOMPANY.DE = {
   admin_server = xyz.mycompany.de
   kdc = xyz.mycompany.de
   }

[domain_realm]
.INT.MYCOMPANY.DE = INT.MYCOMPANY.DE
int.mycompany.de = INT.MYCOMPANY.DE
.int.mycompany.de = INT.MYCOMPANY.DE
.mycompany.de = INT.MYCOMPANY.DE
mycompany.de = INT.MYCOMPANY.DE

[logging]
#kdc = console

(server and realm name changed)

Spring security config:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="file:${externalPropertiesPath}/edlgui.properties" />

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="kerberosAuthenticationProvider" />
    </authentication-manager>

    <http use-expressions="true">
        <intercept-url pattern="/login.jsp" access="permitAll" />
        <intercept-url pattern="/admin/**" access="hasRole('${edl.gui.authorization.requiredrole}')" />
        <form-login login-page="/login.jsp" username-parameter="username" password-parameter="password" default-target-url="/admin"/>
        <logout logout-url="/logout" logout-success-url="/login.jsp" />
        <http-basic />
        <access-denied-handler ref="edlGuiAccessDeniedHandler"/>
    </http>

    <beans:bean id="edlGuiAccessDeniedHandler" class="edl.security.EdlGuiAccessDeniedHandler">
        <beans:constructor-arg value="/login.jsp"/>
    </beans:bean>

    <beans:bean id="kerberosAuthenticationProvider" class="org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider">
        <beans:property name="kerberosClient">
            <beans:bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient">
                <beans:property name="debug" value="false" />
            </beans:bean>
        </beans:property>
        <!-- TODO replace dummy user service -->
        <beans:property name="userDetailsService" ref="ldapUserDetailsService" />
    </beans:bean>

    <beans:bean class="org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig">
        <beans:property name="debug" value="false" />
        <!-- externalPropertiesPath path = /opt/pksvc/tomcat/current/conf -->
        <beans:property name="krbConfLocation" value="file:${externalPropertiesPath}/krb5.conf"/>
    </beans:bean>

    <!-- Get User Details via LDAP -->
    <!-- It would be nice to do this via Kerberos, however that requires a keytab -->
    <ldap-user-service id="ldapUserDetailsService"
        server-ref="activeDirectoryLdap"
        user-search-base="${edl.gui.ldap.usersearchbase}"
        user-search-filter="${edl.gui.ldap.usersearchfilter}"
        group-search-base="${edl.gui.ldap.groupsearchbase}"
        group-role-attribute="${edl.gui.ldap.grouproleattribute}"
        group-search-filter="${edl.gui.ldap.groupsearchfilter}"
        user-details-class="person"/>
    <ldap-server id="activeDirectoryLdap"
        url="${edl.gui.ldap.url}"
        manager-dn="${edl.gui.ldap.managerdn}"
        manager-password="${edl.gui.ldap.managerpw}"
        root="${edl.gui.ldap.root}"/>

</beans:beans>

When I try to login the only thing I see from the kerberos debug output is:

Java config name: file:/opt/pksvc/tomcat/current/conf/krb5.conf
getRealmFromDNS: trying mycompany.de

(I would expect to see 'KrbAsReq creating message' and 'KrbKdcReq send' entries)

And from spring:

2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2015-08-04 10:07:42.986 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2015-08-04 10:07:42.986 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@64656737. A new one will be created.
2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 3 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2015-08-04 10:07:42.987 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 4 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2015-08-04 10:07:42.987 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
2015-08-04 10:07:42.987 DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider
2015-08-04 10:07:42.987 DEBUG o.s.s.k.a.sun.SunJaasKerberosClient - Trying to authenticate KieselGun with Kerberos
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Kerberos authentication failed
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@72f106b0
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.SimpleUrlAuthenticationFailureHandler - Redirecting to /login.jsp
2015-08-04 10:07:42.993 DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to '/edl-gui/login.jsp'
2015-08-04 10:07:42.993 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2015-08-04 10:07:42.994 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2015-08-04 10:07:43.042 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2015-08-04 10:07:43.043 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2015-08-04 10:07:43.043 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@64656737. A new one will be created.
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 3 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 4 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - pathInfo: both null (property equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - queryString: both null (property equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - requestURI: arg1=/edl-gui/admin; arg2=/edl-gui/login.jsp (property not equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.HttpSessionRequestCache - saved request doesn't match
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2015-08-04 10:07:43.044 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 172.20.65.226; SessionId: F2C563CA5780A3024AE7D89390CE0AB1; Granted Authorities: ROLE_ANONYMOUS'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2015-08-04 10:07:43.045 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2015-08-04 10:07:43.045 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login.jsp'; against '/login.jsp'
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /login.jsp; Attributes: [permitAll]
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 172.20.65.226; SessionId: F2C563CA5780A3024AE7D89390CE0AB1; Granted Authorities: ROLE_ANONYMOUS
2015-08-04 10:07:43.045 DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@265c45f7, returned: 1
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2015-08-04 10:07:43.045 DEBUG o.s.security.web.FilterChainProxy - /login.jsp reached end of additional filter chain; proceeding with original chain
2015-08-04 10:07:43.046 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
2015-08-04 10:07:43.046 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2015-08-04 10:07:43.046 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

So it seems the user gets authenticated as anonymous, after which I get back to the login page since anonymous users have no access.

Can anyone tell me what's wrong with my configuration? Or how I could further analyse this?


回答1:


I'm not sure how jdk's krb implementation differ between linux and win. Obviously there are some differences because in linux jdk will try to find default /etc/krb5.conf and there is one other default location I don't remember right now. I assume in win similar tweaks are in place for jdk. You could event temporarily rename default krb5.conf file to be sure it's not used(and getting wrong config).

I'm shooting in dark here but let's make a random guess. I had a lot of various type of troubles when I make all those samples but eventually got all working. At some point(in linux) when I was totally lost if failures was caused by our spring-security-kerberos libs or something to do with a kerberos settings, etc, I found it to very valuable to test kerberos settings outside of a jdk. See http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/#troubleshooting and especially trying to connect ldapsearch from linux into AD. You don't need to use keytabs because kinit should allow you to get ticket from AD if settings are right.

One thing I have there is:

[realms]
EXAMPLE.ORG = {
  kdc = WIN-EKBO0EQ7TS7.example.org:88
}

I believe I had this port 88 for a reason and maybe there are some different defaults linux/win jdk's if none are defined.

Other think is supported enctypes if those are different used by AD and what linux jdk support. This is something you should see from jdk internal krb debug logs. Also if you are able to kinit against AD from linux, klist will then show key enctypes.




回答2:


I found out that in both my local environment on windows and the linux environment the krb5.conf specified in the GlobalSunJaasKerberosConfig krbConfLocation (see below) was not used. Although the debug output showed this file the changes made there had no effect. In my windows environment I had a correctly setup kerberos configuration (I still don't know where that is, I don't have a krb5.ini anywhere...) in the linux environment I did not. As a result kerberos failed in the linux environment.

I managed to workaround this by setting the environment variables java.security.krb5.realm and java.security.krb5.kdc (see https://blogs.oracle.com/wangwj/entry/kerberos_programming_on_windows). With these set kerberos authentication worked.

The krbConfLocation from this bean was not used:

<beans:bean class="org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig">
        <beans:property name="debug" value="false" />
        <beans:property name="krbConfLocation" value="file:${externalPropertiesPath}/krb5.conf"/>
    </beans:bean>


来源:https://stackoverflow.com/questions/31804452/how-to-configure-kerberos-on-tomcat-linux-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!