spring cloud、gradle、父子项目、微服务框架搭建---spring secuity oauth2、mysql 授权(九)

文章目录

    • 一、
    • 二、授权服务
      • 2.1 初始化表结构
      • 2.2 引入依赖
      • 2.3 自定义 用户详情类 UserDetailsService
      • 2.4 授权配置 AuthorizationServerConfiguration
      • 2.5 Web安全配置 WebSecurityConfiguration
      • 2.6 默认生成接口
    • 三、资源服务
      • 3.1 引入依赖
      • 3.2 资源服务 ResourceServerConfig
    • 四、授权测试
      • 4.1 授权码模式
        • (1) 获取code
        • (2)获取授权
      • 4.2 账号密码模式
      • 4.3 请求资源服务,忽略鉴权接口
      • 4.4 请求资源服务,需要鉴权接口
      • 4.5 刷新access_token

一、

新建两个服务
1.授权服务 端口号:11007
2.资源服务 端口号:11004

资源服务可以是订单服务、用户服务、商品服务等等

当然这两个服务也可以合并到一起, 依次顺序AuthorizationServerConfiguration、ResourceServerConfig、WebSecurityConfiguration;

WebSecurityConfiguration 会覆盖ResourceServerConfig的部分配置
例如 authorizeRequests().antMatchers().


二、授权服务

2.1 初始化表结构

sql: https://github.com/spring-attic/spring-security-oauth/blob/main/spring-security-oauth2/src/test/resources/schema.sql

在mysql执行报错时,注意字段为LONGVARBINARY类型,对应mysql的blob类型

表明说明
oauth_client_details客户端账号密码、授权、回调地址等重要信息; 手动插入数据
oauth_access_token存储access_token。 授权成功后自动写入数据,过期后不会删除,但再次获取授权会覆盖
oauth_refresh_token存储refresh_token。授权成功后自动写入数据,过期后不会删除,但再次获取授权会覆盖
oauth_code存储授权码。authorization_code类型的授权code
oauth_approvals存储授权成功的客户端信息。
oauth_client_token存储从服务端获取的token数据。 JdbcClientTokenServices 已经被标记为@Deprecated ,估计已经弃用
clientDetails自定义oauth_client_details表的详情表

oauth_client_token、ClientDetails 暂时无用、可以不用创建

insert一条oauth_client_details数据

INSERT INTO `oauth_client_details` VALUES('inside001', NULL, '$2a$10$FCaIYtevbAi5HCXF5PeSVO7zFQgyP7XbPF0zXip7FEL1UrBoE2PyK', 'read', 'client_credentials,authorization_code,password,refresh_token','http://www.baidu.com', NULL, NULL, NULL, NULL, NULL);

2.2 引入依赖

implementation(‘org.springframework.cloud:spring-cloud-starter-oauth2:3.0.0-RC1’)

2.3 自定义 用户详情类 UserDetailsService

package com.xxxx.oauth.service.impl;import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;@Service
public class CustomerUserDetailsServiceImpl implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {String password = new BCryptPasswordEncoder().encode("1");return new User(username, password, AuthorityUtils.createAuthorityList("test"));}
}

必须继承org.springframework.security.core.userdetails.UserDetailsService
对于loadUserByUsername的实现, 真实业务可能需要验证username,验证roles等等, 现在直接返回不验证

2.4 授权配置 AuthorizationServerConfiguration

package com.xxxx.oauth.oauth2;import com.xxxx.oauth.service.impl.CustomerUserDetailsServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;/*** 授权服务配置** @author Administrator*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {@Autowired@Qualifier("authenticationManagerBean")private AuthenticationManager authenticationManager;@Autowiredprivate DataSource dataSource;/*** 存储令牌,采用数据库* @return*/@Beanpublic TokenStore JdbcTokenStore() {return new JdbcTokenStore(dataSource);}/*** 授权码,采用数据库* @return*/@Beanpublic AuthorizationCodeServices authorizationCodeServices() {return new JdbcAuthorizationCodeServices(dataSource);}/*** 授权信息,采用数据库* @return*/@Beanpublic ApprovalStore jdbcApprovalStore(){return new JdbcApprovalStore(dataSource);}/*** 客户端client服务,采用数据库,且设置加密方式* @return*/@Beanpublic ClientDetailsService jdbcClientDetailsService(){JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);jdbcClientDetailsService.setPasswordEncoder(passwordEncoder());return jdbcClientDetailsService;}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 自定义 实现用户类*/@Autowiredprivate CustomerUserDetailsServiceImpl customerUserDetailsServiceImpl;/*** 配置端点* @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {/******令牌服务配置*********************************************************************/DefaultTokenServices tokenServices = new DefaultTokenServices();// 存储令牌tokenServices.setTokenStore(JdbcTokenStore());// 是否允许刷新令牌tokenServices.setSupportRefreshToken(true);// 是否重复使用刷新令牌(直到过期)tokenServices.setReuseRefreshToken(true);// 客户端client服务tokenServices.setClientDetailsService(jdbcClientDetailsService());// 用来控制令牌存储增强策略tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());// AccessToken有效时间,优先取数据库中的配置,如果未配置,此处才会生效tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(7));// RefreshToken有效时间,优先取数据库中的配置,如果未配置,此处才会生效tokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));/******端点配置*********************************************************************///认证管理器endpoints.authenticationManager(authenticationManager);//用户数据endpoints.userDetailsService(customerUserDetailsServiceImpl);//令牌存储endpoints.tokenStore(JdbcTokenStore());//令牌端点的请求方式, 默认是POSTendpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);//令牌服务endpoints.tokenServices(tokenServices);//authorization_code类型的授权,code写入DB,  不配置此项则默认内存endpoints.authorizationCodeServices(authorizationCodeServices());endpoints.approvalStore(jdbcApprovalStore());}/*** 配置客户端client* @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//client服务clients.withClientDetails(jdbcClientDetailsService());}/*** 安全约束* @param security* @throws Exception*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security//允许客户端使用表单方式发送请求token的认证//如果未设置,则需要再http的Authorization中设置授权.allowFormAuthenticationForClients()// 接口/oauth/token_key的权限    默认拒绝所有 denyAll()  已通过身份验证 isAuthenticated()   permitAll() 公开的.tokenKeyAccess("isAuthenticated()")// 接口/oauth/check_token的权限   默认拒绝所有 denyAll()  已通过身份验证 isAuthenticated()  permitAll() 公开的.checkTokenAccess("isAuthenticated()");}
}

2.5 Web安全配置 WebSecurityConfiguration

package com.xxxx.oauth.oauth2;import com.xxxx.oauth.service.impl.CustomerUserDetailsServiceImpl;
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.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/**
* @author Administrator
/*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {/*** 自定义 实现用户类*/@Autowiredpublic CustomerUserDetailsServiceImpl customerUserDetailsServiceImpl;/*** 重新实例化 AuthenticationManager Bean*/@Override@Bean()public AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 授权管理配置** @param authManager* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder authManager) throws Exception {authManager.userDetailsService(customerUserDetailsServiceImpl);}/*** 安全约束配置** @param webSecurity* @throws Exception*/@Overridepublic void configure(WebSecurity webSecurity) throws Exception {//解决静态资源被拦截的问题//web.ignoring().antMatchers("/favicon.ico", "/asserts/**");}@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.userDetailsService(customerUserDetailsServiceImpl).formLogin().permitAll().and().authorizeRequests()// 自定义的一些接口,可匿名访问.antMatchers("/test/**", "/test1/**").permitAll()// 静态文件,可匿名访问.antMatchers( "/**/*.css", "/**/*.js").permitAll()//排除上面可匿名访问外,其他全部需要鉴权认证.anyRequest().authenticated()// 关闭跨域保护;.and().csrf().disable();}
}

2.6 默认生成接口

/oauth/authorize:授权端点 ,固定授权入口路径 ,也是授权服务器的用户允许授权的页面
/oauth/token :获取令牌端点
/oauth/confirm_access:用户确认授权提交端点
/oauth/error:授权服务错误信息端点
/oauth/check_token:用于资源服务访问的令牌解析端点
/oauth/token_key:提供公有密钥的端点,如果使用 JWT 令牌的话


三、资源服务

3.1 引入依赖

implementation(‘org.springframework.cloud:spring-cloud-starter-oauth2:3.0.0-RC1’)

3.2 资源服务 ResourceServerConfig

package com.xxxx.order.oauth2;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;/*** @author Administrator*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.formLogin().permitAll().and().authorizeRequests()// 自定义的一些接口,可匿名访问.antMatchers("/hello/sayHello", "/test/**").permitAll()//排除上面可匿名访问外,其他全部需要鉴权认证.anyRequest().authenticated()// 关闭跨域保护;.and().csrf().disable();}/*** 资源服务令牌解析服务 配置远程ResourceServerTokenServices后,可不用设置yml远程security.oauth2配置** @return*/@Beanpublic ResourceServerTokenServices tokenService() {//使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secretRemoteTokenServices service=new RemoteTokenServices();service.setCheckTokenEndpointUrl("http://localhost:11007/oauth/check_token");service.setClientId("inside001");service.setClientSecret("1");return service;}
}

四、授权测试

4.1 授权码模式

(1) 获取code

浏览器请求授权码:http://localhost:11007/oauth/authorize?client_id=inside001&response_type=code&redirect_uri=http://www.baidu.com

client_id和redirect_uri的参数必须auth_client_details表中插入的数据

登录授权完成后浏览器会重定向到:https://www.baidu.com/?code=R0RtrN 此时R0RtrN为授权码

(2)获取授权

post请求地址: http://localhost:11007/oauth/token
body中参数 x-wwww-form-urlencoded

grant_type:authorization_code
code:R0RtrN    上一步获取的code
client_id:inside001
client_secret:1
redirect_uri:http://www.baidu.com

响应结果:

  {"access_token": "b9d0bf39-47d2-43bd-ade4-abf4fdf8cd73","token_type": "bearer","refresh_token": "e0898a7f-f2d5-4d91-81b4-9e259ede88a9","expires_in": 3599,"scope": "read"}

在这里插入图片描述

4.2 账号密码模式

post请求地址: http://localhost:11007/oauth/token

请求body:
body中参数 x-wwww-form-urlencoded

grant_type:password
client_id:inside001
client_secret:1
username:inside001
password:1

username就是自定义用户详情类CustomerUserDetailsServiceImpl.loadUserByUsername验证处理,目前未验证,可随便输入

响应结果:

{"access_token": "b9d0bf39-47d2-43bd-ade4-abf4fdf8cd73","token_type": "bearer","refresh_token": "e0898a7f-f2d5-4d91-81b4-9e259ede88a9","expires_in": 3599,"scope": "read"
}

在这里插入图片描述

4.3 请求资源服务,忽略鉴权接口

因为在资源服务的ResourceServerConfig配置中,configure(HttpSecurity http)方法下,.antMatchers(“/hello/sayHello”, “/test/**”).permitAll() 配置了

接口直接请求, 例如:http://localhost:11004/hello/sayHello

4.4 请求资源服务,需要鉴权接口

请求:csshttp://localhost:11004/hello/passwordEncoder?pwd=1

在请求header中添加access_token:Authorization:Bearer 33453e78-cc4b-4ca8-8d5d-bbfd719a1f8b

在这里插入图片描述

4.5 刷新access_token

正常情况下,access_token有效时间小于refresh_token有效时间,access_token失效后可利用refresh_token重新获取access_token, 当refresh_token失效后就需要重新获取授权。

post请求地址: http://localhost:11007/oauth/token

body中参数 x-wwww-form-urlencoded

grant_type:refresh_token
refresh_token:0f941d67-da95-479c-bef4-435b5c823402
client_id:inside001
client_secret:1

在这里插入图片描述





本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/95502.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据组件-Flume集群环境的启动与验证

🥇🥇【大数据学习记录篇】-持续更新中~🥇🥇 个人主页:beixi 本文章收录于专栏(点击传送):【大数据学习】 💓💓持续更新中,感谢各位前辈朋友们支持…

Java object类

一、JDK类库的根类:obiect 1、这个类中的方法都是所有子类通用的。任何一个类默认继承object。就算没有直接继承,最终也会间接继承。 2、obiect类当中有哪些常用的方法?我们去哪里找这些方法呢? 第一种方法:去源代码当中。(但是这种方式比较麻烦,源代…

【从0学习Solidity】合约入门 Hello Web3

【学习Solidity的基础】入门智能合约开发 Hello Web3 📱不写代码没饭吃上架主页 在强者的眼中,没有最好,只有更好。我们是全栈开发领域的优质创作者,同时也是阿里云专家博主。 ✨ 关注我们的主页,探索全栈开发的无限…

【SQL】关系模型与查询和更新数据

一、关系模型 1.1 主键 主键是关系表中记录的唯一标识。主键的选取非常重要:主键不要带有业务含义,而应该使用BIGINT自增或者GUID类型。主键也不应该允许NULL。 可以使用多个列作为联合主键,但联合主键并不常用。 1.2 外键 FOREIGN KEY …

Compose学习 - 环境配置及compose、kotlin插件、gradle、AndroidStudio版本对应关系

最近学习Compose,一开始学习的Compose版本是1.1.1,学习的过程中发现, LazyHorizontalGrid这个方法只有在1.2.0以后版本才支持。 想着既然要升级,直接用最新的好了。后面按照官网建议,下载了最新的AndroidStudio&#…

设计模式-7--代理模式(Proxy Pattern)

一、什么是代理模式(Proxy Pattern) 代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(代理)充当另一个对象(真实对象)的接口,以控制对该对象的…

如何飞速成为开源贡献者(Contributor)

如何飞速成为开源贡献者Contributor 一、环境信息1.1 硬件信息1.2 软件信息 二、Git安装2.1 Git介绍2.2 Git下载安装 三、开源项目选定四、GitHub参与开源流程4.1 Fork项目4.2 SSH配置4.2.1 为什么要配置SSH4.2.2 如何配置SSH 4.3 Clone项目4.4 IDEA关联4.5 PR生成4.6 PR提交 一…

SpringCloud入门实战(十五)分布式事务框架Seata简介

📝 学技术、更要掌握学习的方法,一起学习,让进步发生 👩🏻 作者:一只IT攻城狮 ,关注我,不迷路 。 💐学习建议:1、养成习惯,学习java的任何一个技术…

虚拟世界指南:从零开始,一步步教你安装、配置和使用VMware,镜像ISO文件!

本章目录 CentOS简介镜像下载一、新建虚拟机(自定义)1、进入主页,在主页中点击“创建新的虚拟机”2、点击创建虚拟机创建自己的虚拟机。可以选择自定义3、在“硬件兼容性(H)中选择:Workststion 15.x” ->下一步4、选择“稍后安…

牛客网刷题

牛客网刷题-C&C 2023年9月3日15:58:392023年9月3日16:37:01 2023年9月3日15:58:39 2023年9月3日16:37:01 整型常量和实型常量的区别

已知两地经纬度,计算两地直线距离

文章目录 1 原理公式2 代码实现2.1 JavaScript2.2 C2.3 Python2.4 MATLAB 1 原理公式 在地球上,计算两点之间的直线距离通常使用地理坐标系(例如WGS84)。计算两地直线距离的公式是根据经纬度之间的大圆距离(Great Circle Distanc…

2024王道408数据结构P144 T18

2024王道408数据结构P144 T18 思考过程 首先还是先看题目的意思,让我们在中序线索二叉树里查找指定结点在后序的前驱结点,这题有一点难至少对我来说…我讲的不清楚理解一下我做的也有点糊涂。在创建结构体时多两个变量ltag和rtag,当ltag0时…