implementar implement how example ejemplo como java spring spring-security oauth-2.0

java - implement - oauth2 spring



ConfiguraciĆ³n del contexto de seguridad de primavera para el servidor OAuth2 de 2 patas(credenciales del cliente) (1)

userApprovalHandler : si solo tiene un cliente en su sistema, acepto que los usuarios no deberían tener que aprobarlo para acceder a sus datos.

oauthAuthenticationEntryPoint : Normalmente, si la autenticación falla, el tipo de respuesta es JSON. La documentación dice "Si la autenticación falla y la persona que llama ha solicitado una respuesta de tipo de contenido específica, este punto de entrada puede enviar una, junto con un estado 401 estándar".

clientCredentialsTokenEndpointFilter : emitir un token de acceso es un proceso de dos pasos. Primero, envías al usuario al servidor de recursos para que se autentique. Esta redirección es autenticada por el cliente, idealmente con los encabezados HTTP (clave + secreto). A cambio, el cliente obtiene un código, que puede intercambiarse por un token. No intercambias directamente la clave + el secreto por un token, ya que no contiene la aprobación del usuario.

resourceServerFilter : creo que el propósito de esto es indicar qué clientes tienen acceso a qué recursos, si tiene muchos recursos diferentes.

accessDecisionManager : para OAuth2 necesita un ScopeVoter, por lo que el Administrador predeterminado no es lo suficientemente bueno.

En general : si solo tendrá un cliente que acceda a los recursos en nombre de los usuarios, entonces ¿podría considerar usar Digest en lugar de OAuth2? Y si solo desea autenticar al cliente (no al usuario), OAuth2 es una exageración. La autenticación del cliente en OAuth2 es realmente igual que la Autenticación básica sobre https.

¿Cuál es la configuración mínima para OAuth2 de seguridad de primavera si quiero asegurar un servidor REST para un cliente? No quiero usar ninguna configuración innecesaria o implementar beans innecesarios. ¿Tal vez ya haya un tutorial / ejemplo "fácil" para Spring-security + OAuth2? (Aunque estoy tratando de evitar ser demasiado optimista sobre eso)

Mi configuración de trabajo actual (trabajar con la copia + pasado + wtf del contexto de sparklr) se siente demasiado:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"> <oauth:client-credentials /> </oauth:authorization-server> <sec:authentication-manager alias="clientAuthenticationManager"> <sec:authentication-provider user-service-ref="clientDetailsUserService" /> </sec:authentication-manager> <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> <http-basic entry-point-ref="clientAuthenticationEntryPoint" /> <!-- include this only if you need to authenticate clients via request parameters --> <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> </http> <oauth:resource-server id="resourceServerFilter" resource-id="rest_server" token-services-ref="tokenServices" /> <oauth:client-details-service id="clientDetails"> <oauth:client client-id="the_client" authorized-grant-types="client_credentials" authorities="ROLE_RESTREAD" secret="1234567890" /> </oauth:client-details-service> <http pattern="/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security"> <anonymous enabled="false" /> <intercept-url pattern="/rest/**" access="ROLE_RESTREAD" method="GET" /> <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> </http> <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> <property name="tokenStore" ref="tokenStore" /> <property name="supportRefreshToken" value="false" /> <property name="clientDetailsService" ref="clientDetails" /> <property name="accessTokenValiditySeconds" value="400000" /> <property name="refreshTokenValiditySeconds" value="0" /> </bean> <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans"> <constructor-arg> <list> <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" /> <bean class="org.springframework.security.access.vote.RoleVoter" /> <bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> </list> </constructor-arg> </bean> <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="theRealm" /> </bean> <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="theRealm/client" /> <property name="typeName" value="Basic" /> </bean> <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> <property name="authenticationManager" ref="clientAuthenticationManager" /> </bean> <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> <constructor-arg ref="clientDetails" /> </bean> <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /> <sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true"> <sec:expression-handler ref="oauthExpressionHandler" /> </sec:global-method-security> <oauth:expression-handler id="oauthExpressionHandler" /> <oauth:web-expression-handler id="oauthWebExpressionHandler" /> </beans>

Ya he implementado el authenticationManager (UserDetailsService) como parte de la implementación de la seguridad básica de primavera para que las cuentas y los roles permanezcan en nuestra base de datos.

Los frijoles que realmente no entiendo son:

userApprovalHandler : ¿Por qué necesitaría la aprobación de un usuario en un flujo / otorgamiento de credenciales de cliente ? Parece que sparklr reemplaza el TokenServicesUserApprovalHandler predeterminado para aprobar automáticamente un cliente. ¿Debo hacerlo también para la comunicación entre mis clientes de confianza y el servidor?

oauthAuthenticationEntryPoint : todo lo que sparklr hace al respecto es:

<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="sparklr2" /> </bean>

¿Qué se supone que debe hacer eso?

clientCredentialsTokenEndpointFilter Dice que debería incluir esto solo si quiero autenticar a través de los parámetros de solicitud. Entonces, lo que tengo en mente es exactamente eso: enviar una solicitud GET (?) a mi servidor con el secreto y obtener un token y con ese token acceder a los recursos? Así que estoy pensando, la solicitud del token debe contener el secreto como parámetro de solicitud ..?

resourceServerFilter Me parece que esto indica un servidor de recursos separado? ¿Cómo se aplica si mis recursos están en el mismo servidor que el proveedor de autenticación?

accessDecisionManager No recuerdo haber tenido que usar esto al configurar mi implementación de seguridad Spring personalizada, ¿por qué querría hacerlo ahora?

¡Gracias por leerlo! Espero que alguien pueda responder algunas de mis preguntas ..

Actualizar

He actualizado la configuración al estado de trabajo actual. Ahora puedo solicitar un token de acceso con las credenciales del cliente:

$ curl -X -v -d ''client_id=the_client&client_secret=secret&grant_type=client_credentials'' -X POST "http://localhost:9090/our-server/oauth/token"

y use ese token para acceder a los recursos protegidos:

$ curl -H "Authorization: Bearer fdashuds-5432fsd5-sdt5s5d-sd5" "http://localhost:9090/our-server/rest/social/content/posts"

Todavía se siente como mucha configuración y mis preguntas permanecen. También me pregunto si este es el camino correcto para asegurar la comunicación entre el cliente de confianza y el servidor REST en general.

También parece que la solicitud inicial para el token no es segura, excepto si se realiza a través de https, pero ¿será suficiente?

Además, ¿qué pasa con el token en sí, debo darle una larga vida útil y persistir en el cliente? en cualquier caso, eso significaría capturar una excepción de caducidad del token y luego solicitar una nueva. ¿O debería hacer el apretón de manos para cada solicitud? ¿Qué hay de refrescar el token? Creo que leí en alguna parte que el token de actualización no es seguro para el tipo de concesión de credenciales de cliente ...? ¿Es necesario enviar el token como encabezado HTTP o puedo cambiar eso? No quiero utilizar la pila de cliente de seguridad de primavera para nuestro cliente ya que tiene una configuración bastante antigua (jboss 5) y todo lo que hicimos hasta ahora fue integrar las capacidades de comunicación REST con los parámetros de solicitud.

También ayudaría saber más acerca de toda la configuración de seguridad de primavera, pero la documentación es bastante delgada.

EDITAR

Se actualizó la configuración de seguridad de primavera a nuestro estado actual. Además, aquí está nuestro web.xml:

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>the-display-name</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <servlet> <servlet-name>jersey-serlvet</servlet-name> <servlet-class> com.sun.jersey.spi.spring.container.servlet.SpringServlet </servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>base.package.rest</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jersey-serlvet</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/servlet-context.xml </param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>contextAttribute</param-name> <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.appServlet</param-value> </init-param> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>

Nota: el spring-security-context.xml de arriba se inicializará con el contexto de servlet. El archivo spring-context.xml solo inicializa los beans. (También: Nuestro servidor también tiene algunas vistas, por lo que todos los recursos de descanso se ejecutan bajo / resto, por lo tanto, el patrón url. Pero: Siempre es necesario tener un servlet y un contexto de resorte separados).