SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心

news2025/2/25 21:52:04

目录

1. OAuth2.0 简介

2. 代码搭建 

2.1 认证中心(8080端口)

2.2 资源服务中心(8081端口)

3. 测试结果


1. OAuth2.0 简介

OAuth 2.0(开放授权 2.0)是一个开放标准,用于授权第三方应用程序访问用户在资源所有者(用户)的帐户上存储的受保护资源,而无需共享用户凭据。OAuth 2.0 主要用于在互联网上安全地委托授权,广泛应用于身份验证和授权场景。

以下是 OAuth 2.0 的核心概念和流程:

  1. 角色:

    • 资源所有者(Resource Owner): 拥有受保护资源的用户。
    • 客户端(Client): 第三方应用程序,希望访问资源所有者的受保护资源。
    • 授权服务器(Authorization Server): 负责验证资源所有者并颁发访问令牌的服务器。
    • 资源服务器(Resource Server): 存储受保护资源的服务器,它可以与授权服务器相同,也可以是不同的服务器。
  2. 授权类型:OAuth2.0协议一共支持 4 种不同的授权模式:

                授权码模式:常见的第三方平台登录功能基本都是使用这种模式。

                简化模式:简化模式是不需要客户端服务器参与,直接在浏览器中向授权服务器申请令牌(token),一般如果网站是纯静态页面则可以采用这种方式。

                密码模式:密码模式是用户把用户名密码直接告诉客户端,客户端使用说这些信息向授权服务器申请令牌(token)。这需要用户对客户端高度信任,例如客户端应用和服务提供商就是同一家公司,自己做前后端分离登录就可以采用这种模式。

        

                客户端模式:客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权,严格来说,客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。

2. 代码搭建 

2.1 认证中心(8080端口)

导入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
    </dependencies>

只需要添加两个配置类即可

MyAuthorizationConfig类

@Configuration
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {


    /**
     * 客户端存储策略,这里使用内存方式,后续可以存储在数据库
     */
    @Autowired
    private ClientDetailsService clientDetailsService;

    /**
     * Security的认证管理器,密码模式需要用到
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 配置令牌访问的安全约束
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                //开启/oauth/token_key验证端口权限访问
                .tokenKeyAccess("permitAll()")
                //开启/oauth/check_token验证端口认证权限访问
                .checkTokenAccess("permitAll()")
                //表示支持 client_id 和 client_secret 做登录认证
                .allowFormAuthenticationForClients();
    }
    //配置客户端
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //内存模式
        clients.inMemory()
                //客户端id
                .withClient("test")
                //客户端秘钥
                .secret(new BCryptPasswordEncoder().encode("123456"))
                //资源id,唯一,比如订单服务作为一个资源,可以设置多个
                .resourceIds("order")
                //授权模式,总共四种,1. authorization_code(授权码模式)、password(密码模式)、client_credentials(客户端模式)、implicit(简化模式)
                //refresh_token并不是授权模式,
                .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
                //允许的授权范围,客户端的权限,这里的all只是一种标识,可以自定义,为了后续的资源服务进行权限控制
                .scopes("all")
                //false 则跳转到授权页面
                .autoApprove(false)
                //授权码模式的回调地址
                .redirectUris("http://www.baidu.com"); //可以and继续添加客户端
    }
    /**
     * 令牌存储策略
     */
    @Bean
    public TokenStore tokenStore(){
        return new InMemoryTokenStore();
    }


    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices services = new DefaultTokenServices();
        //客户端端配置策略
        services.setClientDetailsService(clientDetailsService);
        //支持令牌的刷新
        services.setSupportRefreshToken(true);
        //令牌服务
        services.setTokenStore(tokenStore());
        //access_token的过期时间
        services.setAccessTokenValiditySeconds(60 * 60 * 2);
        //refresh_token的过期时间
        services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
        return services;
    }
    /**
     * 授权码模式的service,使用授权码模式authorization_code必须注入
     */
    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        //授权码存在内存中
        return new InMemoryAuthorizationCodeServices();
    }

    /**
     * 配置令牌访问的端点
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                //授权码模式所需要的authorizationCodeServices
                .authorizationCodeServices(authorizationCodeServices())
                //密码模式所需要的authenticationManager
                .authenticationManager(authenticationManager)
                //令牌管理服务,无论哪种模式都需要
                .tokenServices(tokenServices())
                //只允许POST提交访问令牌,uri:/oauth/token
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }
}

SecurityConfig类

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 加密算法
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //todo 允许表单登录
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .and()
                .csrf()
                .disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //从内存中加载用户,实际生产中需要从数据库中加载
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("admin");//后面可以跟and连接
    }



    /**
     * AuthenticationManager对象在OAuth2认证服务中要使用,提前放入IOC容器中
     * Oauth的密码模式需要
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

2.2 资源服务中心(8081端口)

导入依赖和认证中心相同,添加一个配置类ResourceServerConfig

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    /**
     * 配置令牌校验服务,客户端携带令牌访问资源,作为资源端必须检验令牌的真伪
     * TODO 使用JWT作为TOKEN则不必远程调用check_token校验
     */
    @Bean
    public RemoteTokenServices tokenServices() {
        //远程调用授权服务的check_token进行令牌的校验
        RemoteTokenServices services = new RemoteTokenServices();
        // /oauth/check_token 这个url是认证中心校验的token的端点
        services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        //客户端的唯一id
        services.setClientId("test");
        //客户端的秘钥
        services.setClientSecret("123456");
        return services;
    }

    /**
     * 配置资源id和令牌校验服务
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources)  {
        //配置唯一资源id
        resources.resourceId("order")
                //配置令牌校验服务
                .tokenServices(tokenServices());
    }

    /**
     * 配置security的安全机制
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        //#oauth2.hasScope()校验客户端的权限,这个all是在客户端中的scope
        http.authorizeRequests()
                .antMatchers("/**").access("#oauth2.hasScope('all')")
                .anyRequest().authenticated();
    }
}

测试接口

@RestController
public class TestController {
    @GetMapping("/test")
    public String hello() {
        return "hello world";
    }
}

3. 测试结果

访问http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.com

登录,账号admin,密码123456,然后获取授权码

获取令牌

 

访问资源中心

 未携带令牌测试结果

携带令牌测试结果

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java垃圾回收GC过程

GC&#xff08;Gabage Collection&#xff09; 用于回收堆中的垃圾数据 清理方法 1.标记-清理 对数据标记&#xff0c;然后清理 缺点&#xff1a;容易产生内存碎片 2.标记-整理 对标记后的数据清理&#xff0c;剩下数据前移 缺点&#xff1a;每次清理后数据都要迁移&#xff0…

代码随想录二刷 | 回溯 | 组合优化

代码随想录二刷 &#xff5c; 回溯 &#xff5c; 组合优化 剪枝优化 剪枝优化 在遍历的过程中有如下代码&#xff1a; for (int i startIndex; i < n; i) {path.pop_back();backtracking(n, k, i 1);path.pop_back(); }n 4&#xff0c;k 4的话&#xff0c;那么第一层f…

qemu使用

百度qemu bios 问题 坑爹的玩意&#xff0c;编译qemu 还需要python3.5以上 解决方法&#xff1a; CentOS7安装Python3.8-CSDN博客 https://www.cnblogs.com/Oliver.net/p/7211967.html 编译python3.8还由于openssl过低 参考 QEMU启动x86-Linux内核_qemu-system-x86-…

SaaS多租户篇

文章目录 1. 多租户是什么2. 技术组件2.1 如何实现多租户的DB封装2.2 如何实现多租户的redis封装2.3 如何实现多租户的Web和Security封装2.4 如何实现多租户的Job封装2.5 如何实现多租户的 MQ 与 Async 封装&#xff1f;2.6 如何实现多租户的 AOP 与 Util 封装&#xff1f; 3.业…

【Qt之模型视图】5. Qt库提供的视图便捷类

1. 前言 Qt提供了一些便捷的视图类&#xff0c;如QListWidget提供项目列表&#xff0c;QTreeWidget显示多级树结构&#xff0c;QTableWidget提供单元格项的表格。每个类都继承了QAbstractItemView类的行为&#xff0c;QAbstractItemView类实现了项目选择和标题管理的通用行为。…

《WebKit 技术内幕》之五(1): HTML解释器和DOM 模型

第五章 HTML 解释器和 DOM 模型 1.DOM 模型 1.1 DOM标准 DOM &#xff08;Document Object Model&#xff09;的全称是文档对象模型&#xff0c;它可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构。这里的文档可以是 HTML 文档、XML 文档或者 XHTML 文档。D…

ubuntu 相关内容

ubuntu 优盘安装&#xff1a; 台式机安装纯ubuntu系统的操作步骤-CSDN博客https://blog.csdn.net/youngwah292/article/details/127032009?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170583039216800213099577%2522%252C%2522scm%2522%253A%252220140713.1301…

音视频开发ffmpeg

ffmpeg数据结构 重要的结构体 压缩数据 avpacket 帧数据 avframe 管家&#xff1a; avformatcontext 格式上下文 文件是一种协议 解协议&#xff08;http、rtsp rtmp mms tcp udp…&#xff09; AVIOContext URLProtocol URLContext存储音视频中的协议类型和状态 有缓冲区…

74.搜索二维矩阵 - 力扣(LeetCode)

题目描述 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回…

爬虫案例—雪球网行情中心板块数据抓取

爬虫案例—雪球网行情中心板块数据抓取 雪球网行情中心网址&#xff1a;https://xueqiu.com/hq 目标&#xff1a;市场一览板块、热股榜板块、新股预告板块、关注排行榜板块 import datetimeimport requestsheaders {user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10…

算法优化:LeetCode第122场双周赛解题策略与技巧

接下来会以刷常规题为主 &#xff0c;周赛的难题想要独立做出来还是有一定难度的&#xff0c;需要消耗大量时间 比赛地址 3011. 判断一个数组是否可以变为有序 public class Solution {public int minimumCost(int[] nums) {if (nums.length < 3) {// 数组长度小于3时&a…

即插即用篇 | AKConv:具有任意采样形状和任意参数数量的卷积核

基于卷积操作的神经网络在深度学习领域取得了显著的成果,但标准卷积操作存在两个固有缺陷。一方面,卷积操作受限于局部窗口,无法捕捉其他位置的信息,而其采样形状是固定的。另一方面,卷积核的大小固定为kk,呈固定的正方形形状,而参数数量往往随大小呈平方增长。显然,不…

章鱼网络 Community Call #17|打造全新 Omnity 跨链协议

香港时间2024年1月8日12点&#xff0c;章鱼网络举行第17期 Community Call。 对于 Octopus Community 而言&#xff0c;2023年是一个分水岭。我们如期兑现我们的承诺&#xff0c;成功上线了包括 $NEAR Restaking 和 Adaptive IBC 在内的完整的 Octopus 2.0。 自从我们在2023年…

编曲学习:Cubase12导入Cubasis工程的方法!

Steinberg 发布 Cubasis 3 项目导入器&#xff0c;可将 Cubasis 的项目导入到 Cubase 使用https://m.midifan.com/news_body.php?id35635 我偶然看到这个文章&#xff0c;不过发现Cubase12默认好像没有这个选项&#xff0c;心想着要是移动端能和PC端同步&#xff0c;感觉会挺…

腾讯云服务器价格查询,2024更新

腾讯云服务器租用优惠价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器646元15个月&#xff1b;云服务器CVM S5实例2核2G配置280.8元一年、2核4G…

力扣509. 斐波那契数

动态规划 思路&#xff1a; 斐波那契数通式&#xff1a;F(n) F(n - 1) F(n - 2)&#xff1b;以此为状态转移方程&#xff0c;对其进行动态规划&#xff1b;边界条件&#xff1a; F(0) 0F(1) 1使用两个变量来存储上一组结果&#xff1b; class Solution { public:int fib(…

触摸屏监控双速电动机-PLC I/O电路设计

PLC的输入接线电路图 PLC的输入接线电路如图1-21所示。24VDC电源选用0.7mm2的棕色和蓝色软铜导线&#xff0c;弱电信号线用0.5~0.7mm2的黑色或者白色软铜导线。 PLC输入接线图 PLC的输出接线电路图 PLC的输出接线电路如图1-22所示。AC220V接触器型号为CJX2-12&#xff0c;线…

Kubernetes实战(十八)-Pod配置污点和容忍

1 污点 1.1 污点简介 亲和性调度的方式都是站在Pod的角度上&#xff0c;通过在Pod上增加属性来将Pod调度到到指定的节点上&#xff0c;其实也可以站在Node节点的角度上&#xff0c;通过给Node节点设置属性&#xff0c;来决定是否允许Pod调度过来&#xff0c;这就是污点。 No…

数据结构代码实现 —— 单链表【Java】

单链表的概述及性质等在篇不做赘述&#xff0c;有需要可移步以下文章&#xff1a; 《数据结构 C语言版 严蔚敏 第2版》&#xff1a;线性表https://blog.csdn.net/weixin_43551213/article/details/134048025 以下仅展示使用 Java 实现单链表 结点结构定义&#xff1a; publ…

国外邮箱服务:功能、作用与价格全面解析

不同于我们熟悉的国内邮箱服务&#xff08;如163、QQ邮箱等&#xff09;&#xff0c;国外邮箱通常指的是海外提供商所提供的电子邮件服务&#xff0c;如谷歌的Gmail、微软的Outlook、雅虎的Yahoo Mail等&#xff0c;当然也有特殊的比如Zoho Mail邮箱&#xff0c;国内外双版本&a…