简体   繁体   English

CAS + Spring Security Detect本地主机

[英]CAS + Spring Security Detect localhost

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. 我正在尝试使用Spring Security和CAS实现一个应用程序,它在localhost上运行良好,但是当我尝试从外部计算机访问它时,如果该应用程序需要身份验证,它也将重定向到localhost。

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/ 我使用https://172.16.1.50:8443/isxannouncements/访问该应用程序,当需要身份验证时,应访问https://172.16.1.50:8443/cas/login/但应访问https://localhost:8443/isxannouncements/

which ofcourse breaks the application flow. 当然哪个会中断应用程序流程。

my config is 我的配置是

security-cas.xml 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.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 ?? 如何解决这个问题?

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. 我创建了一个名为serviceProperties的bean,并使用了它而不是spring的serviceproperties ,并且我重写了getService的方法以根据用户访问应用程序的域名返回服务。

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. 然后,在Web应用程序上下文中使该bean可用,并通过了会话,已经从请求中提取了域,并将其放入了会话中。

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. 因此,当CasAuthenticationEntryPoint尝试获取服务时,我将通过从附加到其的会话中创建的服务URL传递为服务名称。

We handle this with property files. 我们使用属性文件来处理。 Anything that is specific to a certain environment (ie 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: localhost.properties:

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

test.properties: 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: 然后使用属性文件中的值配置spring security,而不是直接使用上面的配置:

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. CAS在域下工作。 so you should use cas.example.com and define it in the cas.properties 因此您应该使用cas.example.com并在cas.properties中对其进行定义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM