您的位置:首页 > 编程语言 > Java开发

spring-security-oauth2整合

2016-08-04 17:36 190 查看
spring-security-oauth2的项目地址为 https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2

spring-security-oauth2的demo 地址为 https://github.com/spring-projects/spring-security-oauth/tree/master/samples/oauth2

为什么要写

1. spring-security-oauth2的demo 不容易让开发者理解, 配置的内容很多, 没有分解的步骤; 我曾经试着按照文档(https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md)
配置了几次, 结果全失败, 无一成功(说实话, 这是第二次在实际项目中使用spring & oauth,但还是花了不少时间才完全弄清楚);甚至有时候找错误的原因都不好找.

2.Oauth应该属于security的一部分, 但demo并没有将二者分开, 混在一起

3.总结现在, 方便未来

相比于demo,作了哪些改进

1. 将Spring MVC配置与Oauth的配置分开, 互不影响

2.将用户信息存放数据库

3.将ClientDetails数据存放于数据库,并能对数据进行管理

4.扩展ClientDetails基本属性, 添加trusted属性,用于判断Client是否是可信任的

5.取消掉demo中一些不必要的配置

6.针对不同的资源配置不同的权限

7.token存入数据库而不是内存

开始

>>前提: 使用Maven来管理项目; spring-security-oauth的版本号为 1.0.5.RELEASE

1. 添加Maven dependencies; 以下只列出了主要的

[html] view
plain copy

print?





<!--spring security-->

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-core</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-web</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-taglibs</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-acl</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-crypto</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-config</artifactId>

<version>${spring.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security.oauth</groupId>

<artifactId>spring-security-oauth2</artifactId>

<version>1.0.5.RELEASE</version>

</dependency>

2. web.xml配置; 这一步与只使用Spring Security的配置一样.

[html] view
plain copy

print?





</pre><pre code_snippet_id="73897" snippet_file_name="blog_20131119_2_2257675" name="code" class="html"> <filter>

<filter-name>springSecurityFilterChain</filter-name>

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

</filter>

<filter-mapping>

<filter-name>springSecurityFilterChain</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!--contextConfigLocation -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:spring/*.xml</param-value>

</context-param>

<!-- Spring context listener -->

<listener>

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

</listener>

<!--hy mvc-->

<servlet>

<servlet-name>hy</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>hy</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

对于Spring MVC, 需要配置文件hy-servlet.xml, 该文件不是这儿关注的(忽略);

在classpath创建spring目录, 在该目录里创建 security.xml 文件, 这是所有步骤配置的重点.

3.security.xml的配置; 重点开始.

3.1 起用注解; TokenEndpoint与AuthorizationEndpoint需要

[html] view
plain copy

print?





<mvc:annotation-driven/>

<mvc:default-servlet-handler/>

3.2 TokenServices 配置

1). TokenStore, 使用JdbcTokenStore, 将token信息存放数据库, 需要提供一个dataSource对象; 也可使用InMemoryTokenStore存于内存中

[html] view
plain copy

print?





<!--<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore"/>-->

<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">

<beans:constructor-arg index="0" ref="dataSource"/>

</beans:bean>

注: 可以在spring-security-oauth2中找到对应的SQL脚本, 地址为https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2/src/test/resources,
目录中的schema.sql 即是.
(以下不再说明SQL脚本的问题)

2).TokenServices; 需要注入TokenStore

[html] view
plain copy

print?





<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">

<beans:property name="tokenStore" ref="tokenStore"/>

<beans:property name="supportRefreshToken" value="true"/>

</beans:bean>

如果允许刷新token 请将supportRefreshToken 的值设置为true, 默认为不允许

3.3 ClientDetailsService 配置, 使用JdbcClientDetailsService, 也需要提供dataSource, 替换demo中直接配置在配置文件中

[html] view
plain copy

print?





<beans:bean id="clientDetailsService" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">

<beans:constructor-arg index="0" ref="dataSource"/>

</beans:bean>

3.4 ClientDetailsUserDetailsService配置, 该类实现了Spring security中 UserDetailsService 接口

[html] view
plain copy

print?





<beans:bean id="oauth2ClientDetailsUserService"

class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">

<beans:constructor-arg ref="clientDetailsService"/>

</beans:bean>

3.5 OAuth2AuthenticationEntryPoint配置

[html] view
plain copy

print?





<beans:bean id="oauth2AuthenticationEntryPoint"

class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>

3.6 oauth2 AuthenticationManager配置; 在整个配置中,有两个AuthenticationManager需要配置

[html] view
plain copy

print?





<authentication-manager id="oauth2AuthenticationManager">

<authentication-provider user-service-ref="oauth2ClientDetailsUserService"/>

</authentication-manager>

第二个AuthenticationManager用于向获取UserDetails信息,

[html] view
plain copy

print?





<authentication-manager alias="authenticationManager">

<authentication-provider user-service-ref="userService">

<password-encoder hash="md5"/>

</authentication-provider>

</authentication-manager>

userService是一个实现UserDetailsService的Bean

3.7 OAuth2AccessDeniedHandler配置, 实现AccessDeniedHandler接口

[html]&nbs
23ff7
p;view
plain copy

print?





<beans:bean id="oauth2AccessDeniedHandler"

class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>

3.8 UserApprovalHandler配置, 这儿使用DefaultUserApprovalHandler, 这里是实现client是否可信任的关键点,你可以扩展该接口来自定义approval行为

[html] view
plain copy

print?





<beans:bean id="oauthUserApprovalHandler" class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler">

</beans:bean>

3.9 authorization-server配置, 核心

[html] view
plain copy

print?





<oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"

user-approval-handler-ref="oauthUserApprovalHandler">

<oauth2:authorization-code/>

<oauth2:implicit/>

<oauth2:refresh-token/>

<oauth2:client-credentials/>

<oauth2:password/>

</oauth2:authorization-server>

该元素里面的每个标签可设置每一种authorized-grant-type的行为. 如disable refresh-token的配置为

[html] view
plain copy

print?





<oauth2:refresh-token disabled="true"/>

3.10 Oauth2 AccessDecisionManager配置, 这儿在默认的Spring Security AccessDecisionManager的基础上添加了ScopeVoter

[html] view
plain copy

print?





<beans:bean id="oauth2AccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">

<beans:constructor-arg>

<beans:list>

<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>

<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>

<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>

</beans:list>

</beans:constructor-arg>

</beans:bean>

3.11 resource-server配置, 这儿定义两咱不同的resource

[html] view
plain copy

print?





<!--unity resource server filter-->

<oauth2:resource-server id="unityResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>

<!--mobile resource server filter-->

<oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/>

注意: 每个resource-id的值必须在对应的ClientDetails中resourceIds值中存在

3.12 ClientCredentialsTokenEndpointFilter配置, 该Filter将作用于Spring Security的chain 链条中

[html] view
plain copy

print?





<beans:bean id="clientCredentialsTokenEndpointFilter"

class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">

<beans:property name="authenticationManager" ref="oauth2AuthenticationManager"/>

</beans:bean>

3.13 /oauth/token 的http 配置, 用于监听该URL的请求, 核心

[html] view
plain copy

print?





<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="oauth2AuthenticationManager"

entry-point-ref="oauth2AuthenticationEntryPoint">

<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>

<anonymous enabled="false"/>

<http-basic entry-point-ref="oauth2AuthenticationEntryPoint"/>

<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>

<access-denied-handler ref="oauth2AccessDeniedHandler"/>

</http>

3.14 针对不同resource的http配置, 由于上面配置了两个resource, 这儿也配置两个

[html] view
plain copy

print?





<!--unity http configuration-->

<http pattern="/unity/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"

access-decision-manager-ref="oauth2AccessDecisionManager">

<anonymous enabled="false"/>

<intercept-url pattern="/unity/**" access="ROLE_UNITY,SCOPE_READ"/>

<custom-filter ref="unityResourceServer" before="PRE_AUTH_FILTER"/>

<access-denied-handler ref="oauth2AccessDeniedHandler"/>

</http>

<!--mobile http configuration-->

<http pattern="/m/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"

access-decision-manager-ref="oauth2AccessDecisionManager">

<anonymous enabled="false"/>

<intercept-url pattern="/m/**" access="ROLE_MOBILE,SCOPE_READ"/>

<custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER"/>

<access-denied-handler ref="oauth2AccessDeniedHandler"/>

</http>

注意每一个http对应不同的resourceServer. access-decison-manager-ref对应Oauth的AccessDecisionManager

3.15 默认的http配置,给/oauth/** 设置权限

[html] view
plain copy

print?





<http access-denied-page="/login.jsp?authorization_error=2" disable-url-rewriting="true"

authentication-manager-ref="authenticationManager">

<intercept-url pattern="/oauth/**" access="ROLE_USER,ROLE_UNITY,ROLE_MOBILE"/>

<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

<form-login authentication-failure-url="/login.jsp?authentication_error=1" default-target-url="/index.jsp"

login-page="/login.jsp" login-processing-url="/login.do"/>

<logout logout-success-url="/index.jsp" logout-url="/logout.do"/>

<anonymous/>

</http>

到此, securiy.xml 配置完毕.

当然,还有些额外的工作你需要做, 如配置dataSource, 创建数据库, 添加用户用户信息, 管理ClientDetails等等.

Oauth相关的数据都是存放在数据库, 我们就可以根据表结果创建domain来实现管理.

为了方便大家学习与讨论, 我现在把该项目放在了Git OSC上, 访问地址: http://git.oschina.net/shengzhao/spring-oauth-server,
欢迎大家关注.

与文章相关的配置,扩展请访问: http://andaily.com/blog/?cat=19
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: