【OAuth2.0】Spring Security OAuth2.0篇之初识

  • 不吐不快

  

  因为项目需求开始接触OAuth2.0授权协议。断断续续接触了有两周左右的时间。不得不吐槽的,依然是自己的学习习惯问题,总是着急想了解一切,习惯性地钻牛角尖去理解小的细节,而不是从宏观上去掌握,或者说先用起来(少年,一辈子辣么长,你这么着急合适吗?)。好在前人们已经做好了很好的demo,我自己照着抄一抄也就理解了大概如何用,依旧手残党,依旧敲不出好代码。忏悔…

  • WHAT?

  

  项目之中实际使用OAuth2.0实现是用的Spring Security OAuth2.0,一套基于Spring
Security项目的实现,配合Spring Security配置使用。

  总体来讲,自己所理解的这套实现当中,是在Spring Security的基础之上又增加了几部分内容:

  • authorization server

这部分配置算是OAuth2.0的核心配置部分。

该配置涉及:

  client details service(第三方client端信息查询配置)、

  token service(token查询操作相关)、

  authorization code service(授权code获取)、

  user approval handler(用户授权处理)、

  client端的各种grant_type等等。

同时,这部分内容“内置”了两个FrameworkEndpoint(和Controller意义相同):AuthorizationEndpoint和TokenEndpoint,分别对应请求/oauth/authorize和/oauth/token。只要在spring配置文件中开启MVC配置就能使用并拦截对应

该部分简单配置:

 1 <mvc:annotation-driven/>
2 <mvc:default-servlet-handler/>
3
4 <!-- 1. OAuth2 related config -->
5 <oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
6 user-approval-handler-ref="oauthUserApprovalHandler"
7 user-approval-page="oauth_approval"
8 error-page="oauth_error">
9 <oauth2:authorization-code authorization-code-services-ref="authorizationCodeServices" />
10 <oauth2:implicit/>
11 <oauth2:refresh-token/>
12 <oauth2:client-credentials/>
13 <oauth2:password/>
14 </oauth2:authorization-server>
15
16 <!-- 1.1 client detail service -->
17 <beans:bean id="clientDetailsService" class="com.cyou.nad.bet.oauth.service.impl.CustomJdbcClientDetailsServiceImpl">
18 <beans:constructor-arg index="0" ref="platform_dataSource"/>
19 </beans:bean>
20
21 <!-- 1.2 Config token services-->
22 <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
23 <beans:property name="tokenStore" ref="tokenStore"/>
24 <beans:property name="supportRefreshToken" value="true"/>
25 </beans:bean>
26 <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
27 <beans:constructor-arg index="0" ref="platform_dataSource"/>
28 </beans:bean>
29
30 <!-- 1.3 oauthUserApprovalHandler -->
31 <beans:bean id="oauthUserApprovalHandler" class="com.cyou.nad.bet.oauth.approval.SimpleTokenServiceUserApprovalHandler">
32 <beans:property name="tokenServices" ref="tokenServices"/>
33 <beans:property name="oauthClientDetailsService" ref="oauthClientDetailsService"/><!-- FIXME 考虑直接使用clientDetailService -->
34 </beans:bean>
35
36 <!-- 1.4 authorization code creator -->
37 <beans:bean id="authorizationCodeServices" class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
38 <beans:constructor-arg index="0" ref="platform_dataSource"/>
39 </beans:bean>

Authorization Server

  • 第三方client配置

在spring的这套实现当中,在第三方client端也有自己单独的id、secret和权限,所以从某种程度上来讲,其实client端相当于是一种特殊的user了。

以前使用Spring
Security配置user权限校验的时候,会配置authentication-manager,使用DB的话,还需要提供userService用于查询DB获取用户信息。

这里在配置OAuth的时候,client端也有类似配置,同样需要配置authentication-manager并指定clientDetailService。

实际后续了解更多之后,发现实际校验时,二者封装成的都是类UserDetails的实例

用于client端校验的AuthenticationManager配置:

1 <authentication-manager id="oauth2ProviderManager">
2 <authentication-provider user-service-ref="oauth2ClientDetailsUserService"/>
3 </authentication-manager>
4 <beans:bean id="oauth2ClientDetailsUserService"
5 class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
6 <beans:constructor-arg ref="clientDetailsService"/>
7 </beans:bean>

AuthenticationManager 4
client

  • resource custom filter

在spring
oauth2.0的配置当中,可以单独配置resource-server,指定特定的resource-id。

这个resource-server的用处在于,之后会作为一个custom-filter加到Spring
Security Filter
Chain当中的。当第三方client尝试访问受限资源时,该filter会对client信息和其携带过来的access_token进行校验,校验通过之后才能拿到资源。

resource配置:

1 <oauth2:resource-server id="userResourceServerFilter" resource-id="user" token-services-ref="tokenServices"/>

User resource

    后续作为custom-filter添加到http配置中:

1 <http pattern="/oauth/userInfo*" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"
2 access-decision-manager-ref="oauth2AccessDecisionManager">
3 <anonymous enabled="false"/>
4 <!-- 获取用户信息 -->
5 <intercept-url pattern="/oauth/userInfo*" access="ROLE_UNITY,scope=READ"/>
6 <custom-filter ref="userResourceServerFilter" before="PRE_AUTH_FILTER"/>
7 <access-denied-handler ref="oauth2AccessDeniedHandler"/>
8 </http>

http配置

另外需要一提的就是,OAuth2.0当中还有一个SCOPE的概念,相当于用户对client授权访问自己拥有的某一资源时,可以指定其范围,比如read(只读),
write(可写),或者get_user_info(获取用户信息),
share(分享)等等。一开始没有很好的理解,后来看到别的项目的配置,感觉可以这样想:如果resource对应的是工程的Controller的话,那么scope可以理解为Controller当中的方法,类似于user.getUserInfo()或者user.addShare()等。配置参考:https://github.com/cloudfoundry/uaa/blob/master/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml

添加scope之后,在<http>配置的AccessDecisionManager中就需要添加用于oauth2.0
scope校验相关的voter了:

<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:property name="scopePrefix" value="scope="></beans:property>
</beans:bean>
<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>

AccessDecisionManager配置

  

  关于Spring这套实现的配置,前辈们分享的已经很多了,基本都是类似的配置。后续主要整理对于整体流程和诸如code或token的生成和存储规则相关的东西,最最重要的,还是要把使用过程中遇到的各种问题记录下来才是。

【OAuth2.0】Spring Security OAuth2.0篇之初识,布布扣,bubuko.com

时间: 2024-10-27 04:08:32

【OAuth2.0】Spring Security OAuth2.0篇之初识的相关文章

springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)

项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖  下面是我引入的依赖 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q

Spring Security OAuth2 Demo -- good

1. 添加依赖授权服务是基于Spring Security的,因此需要在项目中引入两个依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springf

Spring Security OAuth2 Demo —— 密码模式(Password)

前情回顾 前几节分享了OAuth2的流程与授权码模式和隐式授权模式两种的Demo,我们了解到授权码模式是OAuth2四种模式流程最复杂模式,复杂程度由大至小:授权码模式 > 隐式授权模式 > 密码模式 > 客户端模式 其中密码模式的流程是:让用户填写表单提交到授权服务器,表单中包含用户的用户名.密码.客户端的id和密钥的加密串,授权服务器先解析并校验客户端信息,然后校验用户信息,完全通过返回access_token,否则默认都是401 http状态码,提示未授权无法访问 本文目标 编写与

spring security oauth2 jwt 认证和资源分离的配置文件(java类配置版)

最近再学习spring security oauth2.下载了官方的例子sparklr2和tonr2进行学习.但是例子里包含的东西太多,不知道最简单最主要的配置有哪些.所以决定自己尝试搭建简单版本的例子.学习的过程中搭建了认证和资源在一个工程的例子,将token存储在数据库的例子等等 .最后做了这个认证和资源分离的jwt tokens版本.网上找了一些可用的代码然后做了一个整理, 同时测试了哪些代码是必须的.可能仍有一些不必要的代码在,欢迎大家赐教. 一.创建三个spring boot 工程,分

Spring security oauth2最简单入门环境搭建

关于OAuth2的一些简介,见我的上篇blog:http://wwwcomy.iteye.com/blog/2229889 PS:貌似内容太水直接被鹳狸猿干沉.. 友情提示 学习曲线:spring+spring mvc+spring security+Oauth2基本姿势,如果前面都没看过请及时关闭本网页. 我有信心我的这个blog应该是迄今为止使用spring security oauth2最简单的hello world app介绍了,如果你下下来附件源码还看不懂,请留言.. 其他能搜到的如h

Spring Security Oauth2 : Possible CSRF detected

Spring Security Oauth2 : Possible CSRF detected 使用Spring Security 作为 Oauth2 授权服务器时,在授权服务器登录授权后,重定向到客户端服务器时,出现了401 Unauthorized 错误.明明已经授权了,为何还会未授权了. 跟踪代码发现,抛出了这个异常: "Possible CSRF detected - state parameter was required but no state could be found&quo

Spring Security 解析(七) —— Spring Security Oauth2 源码解析

Spring Security 解析(七) -- Spring Security Oauth2 源码解析 ??在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring Security .Spring Security Oauth2 等权限.认证相关的内容.原理及设计学习并整理一遍.本系列文章就是在学习的过程中加强印象和理解所撰写的,如有侵权请告知. 项目环境: JDK1.8 Spring boot 2.x Spring Security

Spring Security OAuth2

Spring Security OAuth2 标签(空格分隔): Spring 1. oAuth(Open Authorization) OAuth协议为用户资源的授权(增删改查)提供了一个安全, 开放而又简易的标准. 和以往授权方式不同之处是oAuth的授权不会使第三方触及到用户的账号信息. 即第三方无需使用用户的用户名和密码就可以申请获得该用户的资源授权. 因此oAuth本身第安全是无害的. 2. Spring Security Spring Security是一个安全框架, 可以为Spri

Spring Security 5.0的DelegatingPasswordEncoder详解

本文参考自Spring Security 5.0.4.RELEASE 的官方文档,结合源码介绍了 DelegatingPasswordEncoder,对其工作过程进行分析并解决其中遇到的问题.包括 There is no PasswordEncoder mapped for the id "null" 非法参数异常的正确处理方法. PasswordEncoder首先要理解 DelegatingPasswordEncoder 的作用和存在意义,明白官方为什么要使用它来取代原先的 NoOp