Pregunta

I am trying to implement an application with Spring security and CAS, it works fine on localhost but when I try to access it from an outside machine it and the application needs authentication it redirect to localhost too.

meaning

I access the application using https://172.16.1.50:8443/isxannouncements/ and when it needs authentication it should go to https://172.16.1.50:8443/cas/login/ but instead it goes to https://localhost:8443/isxannouncements/

which ofcourse breaks the application flow.

my config is

security-cas.xml

<bean id="serviceProperties"
      class="org.springframework.security.cas.ServiceProperties">
    <property name="service"
              value="https://localhost:8443/isxannouncements/login"/>
</bean>
<!--
    Allows changing where the CAS Server and CAS Service are easily
    by specifying System Arguments or replacing the values only in one place.
    Could also use external properties file -->
<context:property-placeholder
        system-properties-mode="OVERRIDE" properties-ref="environment"/>
<util:properties id="environment">
    <prop key="cas.service.host">localhost:8443</prop>
    <prop key="cas.server.host">localhost:8443</prop>
</util:properties>

<!-- sends to the CAS Server, must be in entry-point-ref of security.xml -->
<bean id="casEntryPoint"
      class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    <property name="serviceProperties" ref="serviceProperties"/>
    <property name="loginUrl" value="https://localhost:8443/cas/login" />
</bean>

<!-- authenticates CAS tickets, must be in custom-filter of security.xml -->
<bean id="casFilter"
      class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="filterProcessesUrl" value="/login"/>
</bean>

<bean id="casAuthProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    <property name="ticketValidator" ref="ticketValidator"/>
    <property name="serviceProperties" ref="serviceProperties"/>
    <property name="key" value="isxannouncements"/>
    <property name="authenticationUserDetailsService" ref="DBUserServiceDetails"/>
    <property name="statelessTicketCache" ref="statelessTicketCache"/>
</bean>

<bean id="statelessTicketCache" class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
    <property name="cache">
        <bean class="net.sf.ehcache.Cache"
              init-method="initialise" destroy-method="dispose">
            <constructor-arg value="casTickets"/>
            <constructor-arg value="50"/>
            <constructor-arg value="true"/>
            <constructor-arg value="false"/>
            <constructor-arg value="3600"/>
            <constructor-arg value="900"/>
        </bean>
    </property>
</bean>

<bean id="ticketValidator" class="org.jasig.cas.client.validation.Saml11TicketValidator">
    <constructor-arg value="https://localhost:8443/cas" />
    <property name="encoding" value="utf8" />
</bean>

<!-- Handles a Single Logout Request from the CAS Server must be in custom-filter of security.xml -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>

and my security.xml

<security:http pattern="/resources/images" security="none"/>
<security:http use-expressions="true" entry-point-ref="casEntryPoint">
    <security:intercept-url pattern="/login/*"
                            access="permitAll"/>
    <security:intercept-url pattern="/resources/**"
                            access="permitAll"/>
    <security:intercept-url pattern="/logout"
                            access="permitAll"/>
    <security:intercept-url pattern="/errors/**"
                            access="permitAll"/>
    <security:intercept-url pattern="/approve-announcement**"
                            access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/delete-announcement**"
                            access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/edit-announcement**"
                            access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/admin/**"
                            access="hasRole('ROLE_ADMIN')"/>
    <security:intercept-url pattern="/META-INF"
                            access="hasRole('ROLE_USER')"/>
    <security:access-denied-handler error-page="/errors/403"/>

    <security:custom-filter ref="singleLogoutFilter" before="LOGOUT_FILTER"/>
    <security:custom-filter ref="casFilter" position="CAS_FILTER"/>
    <security:port-mappings>
        <security:port-mapping http="8080" https="8443"/>
    </security:port-mappings>

    <security:logout logout-url="/logout"
                     logout-success-url="https://localhost:8443/cas/logout"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="casAuthProvider" />
</security:authentication-manager>

how to fix this ??

¿Fue útil?

Solución

Ok I found a workaround but I did not test it properly,

Inspired by this answer I did the following

since I have two domains that the user might use to access my application, the only way to get the domain the user used was to get from the request and then return it to the security provider.

I created a bean named serviceProperties and used it instead of the serviceproperties of spring, and I overrided the method of getService to return the service based on the domain name that the user to access the application.

Then I made this bean available at Web Application Context, and I passed in the session, I had already extracted the domain from the Request and put it in the Session.

So when the CasAuthenticationEntryPoint tries to get the service, I pass the service URL that I created from the session appended to it is the service name.

Otros consejos

We handle this with property files. Anything that is specific to a certain environment (i.e. your local machine versus your test server) should be in a property file.

For example, create properties files for each environment with something like this:

localhost.properties:

    cas.service.url=http://localhost/login

test.properties:

    cas.service.url=http://mytestserver/login

And then configure spring security with the value from the properties file instead of directly as you have it above:

Your build process would then have a target for each environment to shuffle the appropriate files into place in the final artifact.

CAS works under domain. so you should use cas.example.com and define it in the cas.properties

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top