集成 Spring Security OAuth2.0

最近想在之前的系统里加入oauth2.0服务,于是找到spring security oauth项目主页,发现只有例子和开发人员指南可以参考,例子用的是java config的方式,与现在的系统用xml的方式有点不一致。便自己研究了下,系统里已经集成了spring security,并且用户的认证授权是由CAS提供的。

1、理解 OAuth2.0

1.1 相关引用

理解OAuth2.0 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

开发人员指南 https://www.oschina.net/translate/oauth-2-developers-guide

1.2 理解 Spring Security 的几个概念:
  1. 认证与授权    认证是对访问主体进行合法化认证,不管用的是CAS用户还是JDBC查询出来的用户还是接下来要说的client,我们都需要进行认证,只是CAS这种方式,用户的认证由CAS确定,授权同样也是可以由CAS确定的。授权是对已经认证的主体赋予相应的权限,使之可以访问对于的资源。
  2. 权限校验    主体请求访问被保护资源时,将被保护资源所需的权限和主体所拥护的权限二者进行比对,如果校验通过则用户可以访问被保护资源,否则拒绝访问。
1.3 for example 

用户 admin 需要访问 /admin/user ,这个资源我们需要用户具备 ROLE_ADMIN 这样的角色才能访问,那么 admin 就要具备这样的角色,如果用户 admin 只是具有 ROLE_USER 角色,他密码用户名正确,我们称他是合法用户,也就是 检查 他的票据(用户名密码或者是CAS的票据)是可以认同的,但你不具备访问/admin/user的权限。这个时候返回的应该是403,而不是401。

2、准备工作

2.1 添加依赖

这里加入的是2.0.12.RELEASE,因为parent里有platform-bom的Athens-SR1版本。

<dependency>
	<groupId>org.springframework.security.oauth</groupId>
	<artifactId>spring-security-oauth2</artifactId>
</dependency>
2.2 引入命名空间
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util.xsd
		http://www.springframework.org/schema/security
		http://www.springframework.org/schema/security/spring-security.xsd
		http://www.springframework.org/schema/security/oauth2
		http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

 

3、开始配置

3.1 配置client的认证服务器

这里由于之前集成了CAS,增加 provider 即可。

<authentication-manager alias="authenticationManager">
	<authentication-provider ref="casAuthenticationProvider" />
	<authentication-provider user-service-ref="clientDetailsUserDetailsService" />
</authentication-manager>

这样的方式会生成一个ProviderManager 的 authenticationManager ,ProviderManager 会得到所有的 provider 进行遍历,直到最后没有异常。这里增加的 provider 会对 client 的 id 和 scret进行校验,之前的 provider  处理CAS返回来的信息,一个是对普通用户的认证,一个是对客户端的认证,这两种对于 spring security 来说 都是需要认证的用户。

3.2 client 信息

当然需要知道有什么 有 client 吧。所以 下一步  配置 ClientDetailsUserDetailsService,这里把client当作系统的用户来处理。

<beans:bean id="clientDetailsUserDetailsService"
	class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
	<beans:constructor-arg ref="clientDetailsService" />
</beans:bean>

<oauth2:client-details-service id="clientDetailsService">
	<oauth2:client client-id="123" secret="456" scope="read,write,trust"
		redirect-uri="https://www.baidu.com" authorities="ROLE_CLIENT"
		authorized-grant-types="authorization_code,refresh_token,implicit,client_credentials" />
</oauth2:client-details-service>

这里使用的内存的配置,后期可以修改成 JDBC。建表文件在 github 上  oauth 项目里有。

3.3 配置 TokenServices

既然是rest ,那么就应该是一个无状态的连接。如何确定访问的权限呢,这就通过 token 来识别。配置 TokenServices 、token 的 保存、过期、删除 就由这管理。


<beans:bean id="defaultTokenServices"
	class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
	<beans:property name="tokenStore" ref="tokenStore" />
	<beans:property name="supportRefreshToken" value="true" />
</beans:bean>

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

这里使用的也是内存保存,后期同样需要 修改成 jdbc 的方式。不然重启之后client 又需要用户授权了。

3.4 配置一些默认的处理
<beans:bean id="defaultUserApprovalHandler"
	class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler" />

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

<beans:bean id="oAuth2AccessDeniedHandler"
	class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
3.5 配置 client 的授权服务器
<oauth2:authorization-server
	token-services-ref="defaultTokenServices" client-details-service-ref="clientDetailsService"
	user-approval-handler-ref="defaultUserApprovalHandler">
	<oauth2:authorization-code />
	<oauth2:implicit />
	<oauth2:refresh-token />
	<oauth2:client-credentials />
	<oauth2:password disabled="true" />
</oauth2:authorization-server>

这里禁用了 password 的方式,因为 用户信息是从CAS那里获取的,使用这种方式这样的没有办法认证的,如果一定需要,还要开发一个与CAS服务交互,或者远程调用,或者直接连接数据库,我的另一篇博客里有替代的方式 https://my.oschina.net/taoyuanping/blog/809157

3.6 配置 资源服务器
<oauth2:resource-server id="apiResourceServer"
	resource-id="api-Resource" token-services-ref="defaultTokenServices" />
3.7 配置 http 标签

<http pattern="/oauth/token" create-session="stateless"
	entry-point-ref="oAuth2AuthenticationEntryPoint">
	<csrf disabled="true" />
	<anonymous enabled="false" />
	<intercept-url pattern="/oauth/token" access="hasRole('CLIENT')" />
	<custom-filter ref="clientCredentialsTokenEndpointFilter"
		before="BASIC_AUTH_FILTER" />
	<access-denied-handler ref="oAuth2AccessDeniedHandler" />
</http>

开启client 授权服务器后,框架会自动配置 几个 url ,包括 授权、获取令牌。这里需要对 获取令牌的 请求做认证

加入过滤器 clientCredentialsTokenEndpointFilter

<beans:bean id="clientCredentialsTokenEndpointFilter"
	class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
	<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>

这个过滤器可以对client 进行合法认证,总不能随随便便发个client_id我就发个令牌给你吧。需要关闭 csrf ,用不着的。只有具备 ROLE_CLIENT 的角色才能使用。

3.8 配置资源访问权限

client 的认证服务  授权服务 资源服务 都有了,还需要什么 ,还需要一个 可以对访问资源服务器的入口,或者说对  token 的校验。

<http pattern="/api/**" create-session="stateless"
	entry-point-ref="oAuth2AuthenticationEntryPoint">
	<csrf disabled="true" />
	<anonymous enabled="false" />
	<intercept-url pattern="/api/**" access="hasRole('USER')" />
	<custom-filter ref="apiResourceServer" before="PRE_AUTH_FILTER" />
	<access-denied-handler ref="oAuth2AccessDeniedHandler" />
</http>
  1. 这里的 hasRole('USER') 其实角色 资源的所有着具备的角色,资源的所有者授权给client,client 是不是就具备了这样的角色。还有一种oauth的scope的认证。需要 配置 expression-handler。
  2. <custom-filter ref="apiResourceServer" before="PRE_AUTH_FILTER" /> 会生成一个 OAuth2AuthenticationProcessingFilter 的过滤器,这个过滤器负责认证accass_token的有效性。

4、配置MVC


@Controller
@RequestMapping("/api")
public class UserApi {

	@Autowired
	private UserService userService;

	@ResponseBody
	@RequestMapping(value = "/user", method = RequestMethod.POST)
	public User getUser(Principal principal) {
		User user = userService.findByUsername(principal.getName());
		return user;
	}

}

5、 测试

5.1 获取 code

http://www.yakee.net:8080/framework/oauth/authorize?client_id=123&response_type=code

没有登陆,需要用户登陆

 

登陆用户  admin /123456   cas 返回信息 用户具备  user 角色。

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>admin</cas:user>
        <cas:attributes> 
            <cas:isFromNewLogin>true</cas:isFromNewLogin>
            <cas:authenticationDate>2016-12-15T19:10:18.258+08:00</cas:authenticationDate>
            <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed>
            <cas:authorities>ROLE_REST_SERVICE</cas:authorities>
            <cas:authorities>ROLE_ADMIN</cas:authorities>
            <cas:authorities>ROLE_USER</cas:authorities>
        </cas:attributes>
    </cas:authenticationSuccess>
</cas:serviceResponse>

 

5.2 admin 用户授权客户端 123

页面难看是难看了,但是功能一个不落。

5.3 返回 授权码 code

返回code 参数  NhSB8O

5.4 使用授权码 获取 token

@Test
public void getToken() {
	Map<String, String> params = new HashMap<String, String>();
	params.put("redirect_uri", "https://www.baidu.com");
	params.put("grant_type", "authorization_code");
	params.put("client_secret", "456");
	params.put("client_id", "123");
	params.put("code", "NhSB8O");

	String rsp = null;

	try {
		rsp = WebUtils.doPost("http://www.yakee.net:8080/framework/oauth/token", params, 3000, 15000);

		System.out.println(rsp);

	} catch (Exception e) {
		e.printStackTrace();
	}

}

返回

{
    "additionalInformation":{},
    "expiration":"2016-12-16 07:17:39",
    "expired":false,
    "expiresIn":43199,
    "refreshToken":{
        "expiration":"2017-01-14 19:17:39",
        "value":"58c44eee-67bb-46b0-b98f-5226d2c81214"
    },
    "scope":["read","write","trust"],
    "tokenType":"bearer",
    "value":"eb7cb64d-02b8-4208-9d01-6ec77265f8a2"
}

过期时间真短。

5.5 使用 access_token  获取用户

@Test
public void getUser() {
	Map<String, String> params = new HashMap<String, String>();
	params.put("access_token", "eb7cb64d-02b8-4208-9d01-6ec77265f8a2");

	String rsp = null;

	try {
		rsp = WebUtils.doPost("http://www.yakee.net:8080/framework/api/user", params, 3000, 15000);

		System.out.println(rsp);

	} catch (Exception e) {
		e.printStackTrace();
	}

}

 

发起请求后 过滤链情况

Request received for POST '/api/user':

org.apache.catalina.connector.RequestFacade@1a793b92

servletPath:/api/user
pathInfo:null
headers: 
accept: text/xml,text/javascript,text/html
user-agent: aop-sdk-java
content-type: application/x-www-form-urlencoded;charset=UTF-8
host: www.yakee.net:8080
connection: keep-alive
content-length: 49


Security filter chain: [
  SecurityContextPersistenceFilter
  WebAsyncManagerIntegrationFilter
  HeaderWriterFilter
  OAuth2AuthenticationProcessingFilter
  SecurityContextHolderAwareRequestFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]


************************************************************

返回

{
    "createDate":"2016-12-12 01:42:38",
    "department":"软件研发部",
    "email":"taoyuanping@yakee.net",
    "enabled":true,
    "id":2,
    "modifyDate":"2016-12-12 01:42:38",
    "name":"陶远平",
    "password":"$2a$10$lH8n4sStC44KjG7GPsrgneBcZp.trl9U8WCH06BERpN6DAx4U30HK",
    "phone":"15220176365",
    "username":"admin"
}

6、后续配置

开发 client 的管理,将信息保存到数据库。将token保存到数据库并且增加过期时间,优化用户授权页面,错误信息等,配置expression-handler,支持oauth的scope权限认证。最后配置https,使用OpenSSL生成自签证书即可,使用http调用rest服务可不是明智之举。

 

转载于:https://my.oschina.net/taoyuanping/blog/806601

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以为您提供关于Spring Security OAuth 2.0实现的中文回答。 Spring Security OAuth 2.0是Spring Security框架的一部分,它为应用程序提供了OAuth 2.0认证和授权的支持。OAuth 2.0是一种常用的授权协议,它允许用户授权第三方应用程序访问他们的受保护资源。Spring Security OAuth 2.0实现了OAuth 2.0协议中的授权服务器和资源服务器两个角色。 要使用Spring Security OAuth 2.0,您需要完成以下步骤: 1.添加Spring Security OAuth 2.0依赖项:在Maven或Gradle项目中,您需要添加Spring Security OAuth 2.0的依赖项。例如,在Maven项目中,您可以添加以下依赖项: ```xml <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.6.RELEASE</version> </dependency> ``` 2.配置OAuth 2.0客户端:您需要配置OAuth 2.0客户端,以便您的应用程序可以访问受保护的资源。这通常涉及到注册应用程序并获取客户端ID和客户端密钥。 3.配置授权服务器:您需要配置授权服务器,以便用户可以授权应用程序访问他们的受保护资源。授权服务器可以与您的应用程序集成,也可以作为单独的服务运行。 4.配置资源服务器:您需要配置资源服务器,以便它可以验证访问令牌并授予对受保护资源的访问权限。 5.保护受保护的资源:您需要配置Spring Security以保护受保护的资源,并确保只有经过身份验证和授权的用户可以访问它们。 以上是使用Spring Security OAuth 2.0实现OAuth 2.0认证和授权所需的主要步骤。如果您需要更详细的指导,请参考Spring Security OAuth 2.0的官方文档。 ### 回答2: Spring Security OAuth2.0是一个基于Spring框架的安全认证和访问控制框架,它实现了OAuth2.0协议并提供了OAuth2.0客户端和服务器的实现,可以帮助Spring应用程序保护和管理访问资源。 Spring Security OAuth2.0的实现主要包括客户端和服务器的认证和授权过程。在客户端认证过程中,首先会发送请求获取访问令牌,然后将访问令牌发送给资源服务器以访问所需的资源。在服务器认证过程中,首先要检验客户端是否有访问资源的权限,如果有则颁发授权码或访问令牌,否则返回错误信息。 在实现中,Spring Security OAuth2.0主要涉及到四个角色:资源拥有者、客户端、授权服务器和资源服务器。资源拥有者可以是用户,识别资源拥有者是通过认证授权服务器来完成的。客户端是向授权服务器申请OAuth2.0访问令牌的应用程序。授权服务器是用来对客户端进行身份验证和授权的服务器,它可以使用多种身份验证方式和批准策略来验证客户端的请求,然后授权它访问所需的资源。资源服务器是维护、提供API的服务器,它可以验证OAuth2.0访问令牌,然后允许或拒绝客户端的请求。 Spring Security OAuth2.0框架中提供了一些接口和类来实现OAuth2.0的认证和授权过程。例如,OAuth2AuthenticationProcessingFilter是用于授权客户端访问资源的过滤器,它首先对客户端的访问请求进行身份验证,然后检查是否有访问资源的权限。如果客户端有访问权限,则颁发访问令牌。 在实际使用中,Spring Security OAuth2.0可以与其他技术栈集成,例如Spring Boot、Spring Cloud、JavaEE等,可以实现用户级别、角色级别、API级别、组织级别等多种细粒度的访问控制方式,从而帮助企业实现灵活的访问控制。同时,Spring Security OAuth2.0框架也提供了一些扩展配置和插件,可以根据企业自身需求进行二次开发和定制,实现更加高效和安全的应用程序。 ### 回答3: Spring Security是一个功能强大的安全框架,提供了基于应用程序的安全性控制和身份验证机制。而OAuth2.0则是一种允许用户使用第三方应用程序访问资源的框架,并且该框架将安全性设计为一个核心功能。 Spring SecurityOAuth2.0可以结合使用来提高应用程序的安全性。Spring Security OAuth2.0是一个非常特殊的模块,它为OAuth2.0提供了完整的实现。 使用Spring Security OAuth2.0,我们可以实现以下功能: 1. 身份验证和授权管理:提供授权服务器和资源服务器来进行身份验证和授权的管理。 2. Token管理:生成和管理OAuth2.0令牌以确保安全性。 3. 支持多种授权类型:支持授权码模式、客户端模式、密码模式、隐式模式等多种授权类型,实现不同场景下的资源访问控制。 4. 集成Spring Boot:Spring Security OAuth2.0被设计成与Spring Boot高度集成,方便易用。 5. 提供公开API:提供了一组公开API,方便第三方应用程序的接入。 Spring SecurityOAuth2.0集成需要我们做以下几个步骤: 1. 在Spring Security配置文件中添加OAuth2.0配置。 2. 定义安全领域对象,包括用户、角色和授权管理等。 3. 实现OAuth2.0的授权服务器和资源服务器。 4. 配置OAuth2.0客户端,使其可以访问受保护的资源。 总之,Spring Security OAuth2.0能够帮助开发者集成身份验证和授权管理功能,并为第三方应用程序提供安全的访问资源方式。它为应用程序提供了更高级别的安全性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值