简体   繁体   中英

Spring Security shows default login instead of OAuth2

I am writing a RESTful web service (Jersey running on Tomcat) that needs to authenticate users. The plan is to redirect them to login to Google via OAuth2 . Once they grant us permission to see their email address, we'll know if they are a known user in our system.

I am using Spring Security . I had it working with basic authentication (hard-wired list of users and passwords.) Then I added OAuth2 elements to the XML configuration, but when I access the service from a browser I'm still getting prompted to login by the browser, instead of getting redirected to Google's website. There are no particular errors logged by the console.

Suggestions would be appreciated. Here is my Spring Security configuration file: spring-security.xml (though without the real client's ID and secret.)

<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"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2" 

xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  http://www.springframework.org/schema/security
  http://www.springframework.org/schema/security/spring-security-3.2.xsd
  http://www.springframework.org/schema/security/oauth2 
  http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">

<debug/>

<oauth:client id="oauth2ClientFilter" />

<oauth:resource id="googleOauth2Resource" type="authorization_code" client-id="myclientid.apps.googleusercontent.com" client-secret="myclientsecret" 
    access-token-uri="https://accounts.google.com/o/oauth2/v3/token" user-authorization-uri="https://accounts.google.com/o/oauth2/auth" scope="email" />

<http auto-config='true' xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/V1/**" access="ROLE_USER" />
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
</http>

<oauth:rest-template id="googleOauthRestTemplate" resource="googleOauth2Resource" />

<authentication-manager>
</authentication-manager>

</beans:beans>

Here are the guts of my web.xml file. (Nothing here was changed from when I had the hard-wired list of users and passwords.)

<!-- Require HTTPS for everything except /img (favicon) and /css. -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>HTTPSOnly</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>HTTPSOrHTTP</web-resource-name>
        <url-pattern>*.ico</url-pattern>
        <url-pattern>/img/*</url-pattern>
        <url-pattern>/css/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint> 


<servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <!-- Register resources and providers under com.vogella.jersey.first package. -->
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.foobar.dataservices</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/V1/*</url-pattern>
</servlet-mapping>

<resource-ref>
    <description>TAE DB Connection Pool</description>
    <res-ref-name>jdbc/taeDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

<listener>  
  <listener-class>
   org.springframework.web.context.ContextLoaderListener  
  </listener-class>  
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/spring-security.xml</param-value>
</context-param>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

Suggestions for getting OAuth2 working would be most appreciated.

Removing auto-config="true" from the http element in spring-security.xml got rid of the wrong login form.

This revealed a new error:

Configuration problem: No AuthenticationEntryPoint could be established. Please make sure you have a login mechanism configured through the namespace (such as form-login) or specify a custom AuthenticationEntryPoint with the 'entry-point-ref' attribute

So I added the missing entry-point-ref , and an access-denied-handler while I was at it:

<http xmlns="http://www.springframework.org/schema/security" entry-point-ref="oauthAuthenticationEntryPoint">
    <intercept-url pattern="/V1/**" access="IS_AUTHENTICATED_FULLY" />
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<beans:bean id="oauthAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</beans:bean>

<beans:bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</beans:bean>

The service now launches without logging any errors and does not show the wrong login form.

(But note that it denies permission to all my resources. I thought Spring Security would redirect to Google on behalf of my RESTful service, but maybe my webpage needs to get the authorization token before calling the service? I think that's a new topic though.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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