前言:

OAuth 2.0 是当前授权领域比较流行的标准,它可以为Web应用程序、桌面应用程序、移动设备等提供简单的客户端开发方式。在SpringCloud中提供了SpringCloud Security组件来构建安全的应用程序。SpringCloud Security主要封装了Spring Security、SpringCloud Security OAuth2 等相关实现,这篇文章我们就来介绍一下如何集成OAuth2.0。

正文:

零. OAuth2.0基础知识:

1. 角色:

  • Resource Owner(资源所有者):是能够对受保护的资源授予访问权限的实体,可以是一个用户,这时会称为终端用户。
  • Resource Server(资源服务器):持有受保护的资源,允许持有访问令牌的请求访问受保护资源。
  • Client(客户端):持有资源所有者的授权,代表资源所有者对受保护资源进行访问。
  • Authorization Server(授权服务器):对资源所有者的授权进行认证,成功后向客户端发送访问令牌。

2. 授权流程:

3. 客户端授权类型:

Oauth2.0默认定义了四种授权类型,当然也提供了用于定义额外授权类型的扩展机制。默认的四种授权类型为:

  • Authorization Code:授权码类型。
  • Implicit :简化类型,也称为隐式类型。
  • Resource Owner Password Credentials:密码类型。
  • Client Credential:客户端类型。

一、版本信息:

SpringCloud  Greenwich版本、Springboot  2.1.4.RELEASE版本、OAuth2.0  2.1.2版本

二、授权服务器配置:

1.引入依赖架包:

        <!--oauth2--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency>

2.Springboot启动类上添加@EnableAuthorizationServer注解:

3.配置授权服务器的Oauth2ServiceConfig类:

package com.hanxiaozhang.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;import javax.sql.DataSource;/*** 功能描述: <br>* 〈配置授权服务器〉** @Author:hanxiaozhang* @Date: 2020/7/27*/
@Configuration
public class Oauth2ServiceConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate DataSource dataSource;/*** 配置客户端详情服务** @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory()// 客户端id.withClient("hanxiaozhang")// 允许请求范围.scopes("hanxiaozhang")// 客户端可以使用的授权范围.authorizedGrantTypes("password", "authorization_code", "refresh_token")// 客户端安全码.secret(new BCryptPasswordEncoder().encode("hanxiaozhang"));}/*** 配置Endpoints相关信息:AuthorizationServer、TokenServices、TokenStore、* ClientDetailsService、UserDetailsService** @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager).tokenStore(jdbcTokenStore()).tokenServices(tokenServices());}@Primary@Beanpublic AuthorizationServerTokenServices tokenServices() {DefaultTokenServices tokenServices = new DefaultTokenServices();// access_token:72个小时tokenServices.setAccessTokenValiditySeconds(60 * 60 * 72);// refresh_token:72个小时tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 12);tokenServices.setSupportRefreshToken(true);tokenServices.setReuseRefreshToken(false);tokenServices.setTokenStore(jdbcTokenStore());return tokenServices;}@BeanJdbcTokenStore jdbcTokenStore() {return new JdbcTokenStore(dataSource);}/*** AuthorizationServerSecurityConfigurer继承SecurityConfigurerAdapter,是一个Spring Security安全配置* 提供给AuthorizationServer去配置AuthorizationServer的端点(/oauth/****)的安全访问规则、过滤器Filter** @param security* @throws Exception*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security// 获取token的请求不在拦截.tokenKeyAccess("permitAll()")// 验证通过返回token信息.checkTokenAccess("isAuthenticated()")//  运行客户端使用client_id和client_secret获取token.allowFormAuthenticationForClients();}public static void main(String[] args) {System.out.println("加密: " + new BCryptPasswordEncoder().encode("hanxiaozhang"));System.out.println("比对: " + new BCryptPasswordEncoder().matches("123456", "$2a$10$N5WQVfjpdj.v00dgkBW9cu48iKvke8fu1IsuaKRj5rOc/olmrEetW"));System.out.println("比对: " + new BCryptPasswordEncoder().matches("123456", "$2a$10$Vp1CxPTT/QBmU88jZYzkXOYgIq04Kvfd.o.YYqFn0y6rC5hgO/Yqe"));}}

4.配置Spring Security的SecurityConfig类:

package com.hanxiaozhang.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;import javax.annotation.Resource;/*** 功能描述: <br>* 〈配置Spring Security〉** @Author:hanxiaozhang* @Date: 2020/7/27*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate UserDetailsService userDetail;/*** 配置认证管理器** @return* @throws Exception*/@Override@Bean(name = BeanIds.AUTHENTICATION_MANAGER)public AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/**** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http// 关闭跨域保护.csrf().disable()// 配置HttpSecurity接收的请求.requestMatchers().antMatchers("/login","/oauth/**").and()// 配置URL的权限.authorizeRequests()// 访问/login,/oauth/**不要权限验证,这个配置没有卵用吧,应该配置资源服务的.antMatchers("/login","/oauth/**").permitAll()// 其他所有路径都需要权限校验.anyRequest().authenticated().and()// [解决访问/oauth/authorize/**返回403的问题].httpBasic();}/*** 配置用户** @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetail).passwordEncoder(passwordEncoder());}/*** 配置密码解密器** @return*/@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

5.重写实现UserDetailsService类:

package com.hanxiaozhang.system.service.impl;import com.hanxiaozhang.exception.UserNotLoginException;
import com.hanxiaozhang.security.CurrentUser;
import com.hanxiaozhang.system.dao.MenuDao;
import com.hanxiaozhang.system.dao.UserDao;
import com.hanxiaozhang.system.entity.UserEntity;
import com.hanxiaozhang.util.StringUtil;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;/*** 功能描述: <br>* 〈〉** @Author:hanxiaozhang* @Date: 2020/7/27*/
@Component
public class UserDetailsServiceImpl implements UserDetailsService {@Resourceprivate UserDao userDao;@Resourceprivate MenuDao menuDao;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {UserEntity user = userDao.getByUsername(username);if (user == null) {throw new UserNotLoginException("用户名不存在!");}List<String> permission = menuDao.listPermsByUserId(user.getUserId());// 权限Set<GrantedAuthority> authorities = permission.stream().filter(StringUtil::isNotBlank).map(SimpleGrantedAuthority::new).collect(Collectors.toSet());return new CurrentUser(username, user.getPassword(), user.getUserId(), user.getName(),authorities);}}

6.获取当前用户工具类CurrentUserUtil:

package com.hanxiaozhang.security;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;import java.util.LinkedHashMap;/*** 功能描述: <br>* 〈权限工具类〉** @Author:hanxiaozhang* @Date: 2021/3/24*/
public class CurrentUserUtil {/*** 获取Principal** @return*/private static Object getPrincipal() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication instanceof OAuth2Authentication) {Object principal = ((OAuth2Authentication) authentication).getUserAuthentication().getPrincipal();if (principal instanceof CurrentUser) {return principal;}Object details = ((OAuth2Authentication) authentication).getUserAuthentication().getDetails();if (details instanceof LinkedHashMap && details != null) {principal = ((LinkedHashMap) details).get("principal");if (principal instanceof LinkedHashMap && principal != null) {return principal;}}}return null;}/*** 获取当前用户id** @return*/public static Long getUserId() {if (getPrincipal() instanceof CurrentUser) {return ((CurrentUser) getPrincipal()).getUserId();}return getPrincipal() == null ? null : ((LinkedHashMap) getPrincipal()).get("userId") == null ? null : ((Integer) ((LinkedHashMap) getPrincipal()).get("userId")).longValue();}/*** 获取当前用户名** @return*/public static String getName() {if (getPrincipal() instanceof CurrentUser) {return ((CurrentUser) getPrincipal()).getName();}return getPrincipal() == null ? null : ((LinkedHashMap) getPrincipal()).get("name") == null ? null : (String) ((LinkedHashMap) getPrincipal()).get("name");}/*** 获取当前用户名称** @return*/public static String getUserName() {if (getPrincipal() instanceof CurrentUser) {return ((CurrentUser) getPrincipal()).getUsername();}return getPrincipal() == null ? null : ((LinkedHashMap) getPrincipal()).get("username") == null ? null : (String) ((LinkedHashMap) getPrincipal()).get("username");}public static void main(String[] args) {Object object = null;String str = null;System.out.printf((String) str);System.out.printf((String) object);System.out.printf(String.valueOf(object));}}

三、资源服务器配置:

1.引入依赖架包:

        <!--oauth2--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency>

2.资源服务器配置类ResourceServerConfig:

package com.hanxiaozhang.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.web.context.request.RequestContextListener;import javax.servlet.http.HttpServletResponse;/*** 功能描述: <br>* 〈资源服务器配置类〉** @Author:hanxiaozhang* @Date: 2020/7/31*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable()// 配置异常处理器.antMatcher("/**").exceptionHandling().authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)).and()// 所有请求都需要授权,除去/actuator/**.authorizeRequests().antMatchers("/actuator/**").permitAll().anyRequest().authenticated().and().httpBasic();}/***  解决如下问题:*  Could not fetch user details: class org.springframework.beans.factory.BeanCreationException,*  Error creating bean with name 'scopedTarget.oauth2ClientContext':*  Scope 'request' is not active for the current thread;*  https://blog.csdn.net/wzygis/article/details/21191549** @return*/@Bean@Order(0)public RequestContextListener requestContextListener() {return new RequestContextListener();}}

3.如果资源服务器与授权服务器不在一个服务,需要配置YAML文件:

security:oauth2:client:access-token-uri: http://localhost:9091/oauth/tokenuser-authorization-uri: http://localhost:9091/oauth/authorizeclient-id: hanxiaozhangclient-secret: $2a$10$pjIVEPMujuzQ1m1CWKkZneHhvQUAW1Y/DooXkbl6gApGakwQSy6..clientAuthenticationScheme: formresource:user-info-uri: http://localhost:9091/token/user  # 指定user info的URIprefer-token-info: true   # 是否使用token info,默认为trueauthorization:check-token-access: http://localhost:9091/oauth/check_token

四、使用:

1.模拟登陆,获取access_token:

http://localhost:9091/oauth/token?username=admin&password=123456&grant_type=password&scope=hanxiaozhang&client_id=hanxiaozhang&client_secret=hanxiaozhang

2. 使用access_token获取资源,把access_token放到header中:

http://localhost:9091/currentUser

五、遇到问题:

1.springboot 2.x版本自己集成了spring security,但是在部分微服务中需要去除它,解决方法:

在@SpringBootApplication注解中移除SecurityAutoConfiguration.class和ManagementWebSecurityAutoConfiguration.class

SpringCloud Greenwich版本集成OAuth2.0相关推荐

  1. SpringBoot集成OAuth2.0有新方案了

    背景说明 SpringBoot 2.X已经抛弃了对Spring Security OAuth模块,而是通过Spring Security 5 支持了OAuth 2.0.客户端.资源服务器.授权服务器. ...

  2. 详解比springSecurity和shiro更简单优雅的轻量级Sa-Token框架,比如登录认证,权限认证,单点登录,OAuth2.0,分布式Session会话,微服务网关鉴权

    文章目录 1. 技术选型 2. Sa-Token概述 2.1 简单介绍 2.2 登录认证 2.3 权限认证 3. 功能一览 4. Sa-Token使用 4.1 引入Sa-Token依赖 4.2 Sa- ...

  3. php对接AliGenie天猫精灵服务器控制智能硬件esp8266② 全面认识第三方授权机制 oauth2.0 协议,如何在 php 上搭建 oauth2.0服务端!(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. php对接AliGenie天猫精灵服务器控制智能硬件esp82 ...

  4. SpringCloud Greenwich(五)之nacos、dubbo、Zuul和 gateway集成

    本项目是搭建基于nacos注册中心的springcloud,集成dubbo框架,使用zuul网关和gateway网关 一.框架搭建 (1)项目结构 micro-service  服务提供者 zuul- ...

  5. SpringCloud Greenwich(七)集成dubbo先启动消费者(check=false),然后启动提供者无法自动发现注册

    SpringCloud Greenwich集成dubbo先启动消费者(check=false),然后启动提供者无法自动发现注册问题. 官方说明:修复bug的提交时间 spring-cloud-star ...

  6. SpringCloud Gateway 集成 oauth2 实现统一认证授权_03

    文章目录 一.网关搭建 1. 引入依赖 2. 配置文件 3. 增加权限管理器 4. 自定义认证接口管理类 5. 增加网关层的安全配置 6. 搭建授权认证中心 二.搭建产品服务 2.1. 创建boot项 ...

  7. SpringCloud 2020版本教程0:springcloud 2020版本概述

    Spring cloud赶在2020年最后几天发布了新版本,版本号取名为2020.0.0,取消了英国地铁的命名方式.从H版本之后,全新的命名为2020.x.x.马上快2021年了,为毛不取名为2021 ...

  8. Java开源项目:saas小程序商城(SpringCloud + Oauth2.0 + ShiroRedis + JWT + Gateway + Nacos + Nginx+Vue+Mysql)

    项目采用**SpringCloud **主流开源框架,,设计轻巧,使用简单,开发人员接手与二次开发简单易懂: 项目完成了对阿里云.腾讯云.微信生态的快速接入与代码示例,并成功运用到了商业中,方便大家学 ...

  9. 如何在Cordova Android 7.0.0 以下版本集成最新插件 极光插件为例

    前提 Cordova Android 7.0.0开始改变了项目安卓平台的架构.新建一个空项目分别添加Android 6.4.0 和 Android 7.0.0平台: cordova platform ...

  10. (十)Java B2B2C o2o多用户商城 springcloud架构- SSO单点登录之OAuth2.0登录认证(1)

    2019独角兽企业重金招聘Python工程师标准>>> 之前写了很多关于spring cloud的文章,今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAu ...

最新文章

  1. 博士申请 | 哥本哈根大学招收机器学习和信息检索全奖博士生(年薪34万)
  2. Maven 学习 (0) Maven 简介
  3. top 命令_Linux监控cpu以及内存使用情况之top命令
  4. iOS开发UI篇—九宫格坐标计算
  5. 计算机控制学什么,计算机控制技术专业介绍
  6. 20172304 2017-2018-2 《程序设计与数据结构》第六周学习总结
  7. 异步服务_微服务全链路异步化实践
  8. python最小公倍数 菜鸟_Python实现的求解最小公倍数算法示例
  9. 怎么让电脑屏幕一直亮着_上班族需要注意哪些养生禁忌 一直坐着没好处_百姓民生_新闻...
  10. I/O多路复用之epoll实战
  11. 豆瓣评分9.0以上,数据分析、爬虫、Python等书籍,45本包邮送到家!
  12. 2019如何新建流程图_如何用ppt制作海报和流程图
  13. cvFilter2D() 卷积初步了解
  14. MySQL管理工具安装说明
  15. html5 预览dwg,哪个企业网盘可以实现dwg在线预览?
  16. 计算机论文题目_基于java的毕业设计题目_50例
  17. apk改之理安装教程
  18. html在js中为添加监听,使用addeventlistener为js动态创建的元素添加事件监听
  19. 如何设置ddns动态域名服务实现外网访问
  20. 用防火墙自动拦截攻击IP

热门文章

  1. Spring Boot集成微信扫码登录(实测通过)
  2. [海康威视]-门禁设备告警布防代码C#实现
  3. 运筹说 第41期 | 运输问题硬核知识点梳理—表上作业法求解运输问题
  4. 个人制作:AD库、元件库、封装库及3D模型,免费
  5. 《集异璧》作者侯世达:王维、杨绛与机器翻译的本质
  6. Vue 集成海康h5player,实现ws协议的实时监控播放
  7. 数字化定量分析_数字化驱动下的华夏银行信用卡精细化智能服务
  8. “C语言之父”40年前搞的操作系统复活!Linux、Windows都借鉴过它
  9. mysql数据库详细设计实例_MYSQL数据库设计和数据库设计实例(二)
  10. 中国的顶级黑客-小榕