Security OAuth2简单修改授权码方式

news2024/11/15 13:30:14

问题

用户先通过密码模式获取令牌(前端携带用户名和密码,在网关添加客户端id和客户端密码参数,认证服务通过密码模式发放令牌),此后使用该令牌访问服务。

现在,需要该用户授权给第三方客户端访问这个用户的资源。按标准的情况来说,应该是不能允许用户通过密码模式获取token登录的(通过密码模式获取的token代表的是这个用户完全信任这个客户端而把密码交给这个客户端从而获取到访问令牌),但是有的系统已经这样做了,现在需要在这个的基础上添加授权码模式。

Security OAuth2它本身就自带了授权码模式的实现,但是它需要先跳到1个授权页面,然后点击授权通过后,再跳到第三方客户端的重定向url并携带code,然后code换取token。现在就把一些必要的步骤摘出来(不作严格校验),使得通过密码模式登录的用户能够通过授权码模式授权给指定客户端。

测试

通过密码模式获取访问令牌

http://localhost:53020/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=admin&password=admin
在这里插入图片描述

获取code

http://localhost:53020/uaa/oauth/code?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
在这里插入图片描述

code换取token

http://localhost:53020/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=RSBpm2&redirect_uri=http://www.baidu.com
在这里插入图片描述

使用token访问资源服务

http://localhost:53021/resource/salary/query
在这里插入图片描述

代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo-spring-security-oauth2</artifactId>
        <groupId>com.zzhua</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>distributed-security-uaa</artifactId>

    <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>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.interceptor</groupId>
            <artifactId>javax.interceptor-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot-version}</version>
                <configuration>
                    <mainClass>com.zzhua.UaaServerApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
  port: 53020
  servlet:
    context‐path: /uaa

spring:
  application:
    name: uaa‐service
  main:
    allow‐bean‐definition‐overriding: true
  mvc:
    throw‐exception‐if‐no‐handler‐found: true
  resources:
    add‐mappings: false

management:
  endpoints:
    web:
      exposure:
        include: refresh,health,info,env

UaaServerApplication

@SpringBootApplication
public class UaaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(UaaServerApplication.class, args);
    }
}

MyAuthorizationConfig

@Configuration
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    /*************************令牌端点的安全约束开始************************/
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")        // oauth/token_key公开
                .checkTokenAccess("permitAll()")      // oauth/check_token公开
                .allowFormAuthenticationForClients(); // 允许表单认证,申请令牌
    }
    /*************************令牌端点的安全约束结束************************/


    /*************************配置客户端信息开始************************/
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //内存配置的方式配置用户信息
        clients.inMemory()//内存方式
                .withClient("c1")                                    //client_id
                .secret(passwordEncoder.encode("secret"))            //客户端秘钥
                .resourceIds("salary", "auth")                               //客户端拥有的资源列表
                .authorizedGrantTypes("authorization_code",          //该client允许的授权类型
                        "password",
                        "client_credentials",
                        "implicit",
                        "refresh_token")
                .scopes("all")                                       //允许的授权范围
                .autoApprove(false)                                  //跳转到授权页面
                .redirectUris("http://www.baidu.com");               //回调地址
    }
    /*************************配置客户端信息结束************************/


    /*************************配置令牌服务开始************************/

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    /*
        注意到 {@link ClientDetailsServiceConfiguration#clientDetailsService()}
        {@link AuthorizationServerSecurityConfiguration#configure(ClientDetailsServiceConfigurer)}
     */
    @Autowired
    private ClientDetailsService clientDetailsService;

    /*@Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore(); // 使用基于内存的普通令牌
    }*/
    @Bean
    public JwtAccessTokenConverter accessTokenConvert(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();// [使用JWT令牌]
        converter.setSigningKey("uaa");
        return converter;
    }
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(accessTokenConvert());  // [使用JWT令牌]
    }

    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService); // 客户端详情服务
        service.setSupportRefreshToken(true);                  // 允许令牌自动刷新
        service.setTokenStore(tokenStore());                   // 令牌存储策略-内存
        service.setTokenEnhancer(accessTokenConvert());        // [使用JWT令牌]
        service.setAccessTokenValiditySeconds(7200);           // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200);        // 刷新令牌默认有效期3天
        return service;
    }

    //设置授权码模式的授权码如何存取,暂时用内存方式。
    @Bean
    public AuthorizationCodeServices authorizationCodeServices(){
        return new InMemoryAuthorizationCodeServices();//JdbcAuthorizationCodeServices
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints
                // .pathMapping("/oauth/confirm_access","/customer/confirm_access")//定制授权同意页面
                .authenticationManager(authenticationManager)                      //认证管理器
                .userDetailsService(userDetailsService)                            //密码模式的用户信息管理
                .authorizationCodeServices(authorizationCodeServices())            //授权码服务
                .tokenServices(tokenService())                                     //令牌管理服务
                .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET);
    }
    /*************************配置令牌服务结束************************/
}

MyResourceServerConfig

@Configuration
@EnableResourceServer
public class MyResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("auth") //资源ID
                .tokenStore(tokenStore) // [使用JWT令牌],就不需要调用远程服务了,用本地验证方式就可以了。
                .stateless(true); //无状态模式
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
        http.requestMatcher(r-> true);
    }

    @Bean
    public AuthorizationCodeServices codeServices() {
        return new InMemoryAuthorizationCodeServices();
    }

}

AuthCodeController

@RestController
public class AuthCodeController extends AuthorizationServerConfigurerAdapter {

    private AuthorizationServerEndpointsConfigurer endpoints;

    @PostMapping("oauth/code")
    public String oauthCode(@RequestParam Map<String, String> parameters, Principal principal) {

        AuthorizationRequest authorizationRequest = endpoints.getOAuth2RequestFactory().createAuthorizationRequest(parameters);

        if (!(principal instanceof OAuth2Authentication)) {
            throw new RuntimeException("ERR...");
        }

        OAuth2Authentication oauth2AuthUser = (OAuth2Authentication) principal;
        Authentication userAuthentication = oauth2AuthUser.getUserAuthentication();
        OAuth2Request storedOAuth2Request = endpoints.getOAuth2RequestFactory().createOAuth2Request(authorizationRequest);

        OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, userAuthentication);
        String code = endpoints.getAuthorizationCodeServices().createAuthorizationCode(combinedAuth);
        // NOTE: 当前获取授权码已经完成, 后续的流程: 服务端需要指定客户端携带客户端id和客户端密码,证明客户端自己的身份, 并且携带此code来获取令牌 因为code代表用户对指定客户端的授权
        return code;
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        this.endpoints = endpoints;
    }


}

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

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

相关文章

k8s 进阶实战笔记 | Ingress-traefik(一)

文章目录 traefik认知基本概述基础特性其他ingress对比核心概念和能力 安装部署创建CRD资源RBAC资源创建配置文件部署traefik预期效果 traefik认知 基本概述 ● 官网&#xff1a;https://traefik.cn ● 现代HTTP反向代理、负载均衡工具 ● 它支持多种后台 (Docker, Swarm, Ku…

ElasticSearch IK分词器的MySQL热部署字典(Docker)

1.下载插件源码 找到自己对应ES版本的下载 Releases infinilabs/analysis-ik GitHub 2.添加mysql驱动依赖 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version><…

thinkphp5实现弹出框(下拉框选项动态赋值)

效果图 原理 先执行接口获取动态数据&#xff0c;然后在 layer.open的success回调函数中动态添加html代码片段&#xff0c;通过如下方法&#xff0c;将动态生成的代码插入指定的div中&#xff0c;实现动态赋值的效果。 // 动态获取的数据 var data ......;// 弹出框配置 lay…

Win10关闭弹出提示-‘密码已过期需要更换’

运行—>lusrmgr.msc—>本地用户和组—>用户—>右侧要设置的用户名—>属性—>勾选‘密码永不过期’

laravel使用SSH 隧道连接远程数据库

1、创建SSH隧道 // An highlighted blockssh -i ./id_rsa -N -L 3306:localhost:3306 -p 8848 root192.161.1.1对上述代码的 解释。 命令是一个SSH隧道命令&#xff0c;用于将本地端口3306转发到远程服务器上的3306端口。以下是命令的详细解释&#xff1a;ssh: 调用SSH客户端…

AI工作流:低代码时代的革新者,重塑手机问答类应用生态

在这个数字化迅猛发展的时代&#xff0c;低代码技术正以惊人的速度改变着我们的生活方式。作为低代码人群的先锋&#xff0c;AI工作流技术正在以前所未有的方式&#xff0c;赋予非技术人群实现梦想的能力 &#x1f525;能用AI-低代码传送门&#xff1a;https://www.nyai.chat …

【运维】从一个git库迁移到另一个库

工作目录&#xff1a; /home/java/hosts 10.60.100.194 脚本 hosts / hostsShell GitLab (gbcom.com.cn) 核心代码

AOP实现日志记录需求

首先创建annotation包,包下创建SystemLog类 Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD}) public interface SystemLog {String businessName(); }创建aspect包&#xff0c;包下创建LogAspect类 Component Aspect Slf4j public class LogAspect {Pointc…

给RAG系统做一次全面「体检」,亚马逊开源RAGChecker诊断工具

亚马逊上海人工智能研究院成立于 2018 年&#xff0c;已成为深度学习研究领域的领先机构之一&#xff0c;共发表了&#xff5e;90 篇论文。研究领域包括深度学习的基础理论、自然语言处理、计算机视觉、图机器学习、高性能计算、智能推荐系统、欺诈检测与风险控制、知识图谱构建…

【Redis分析】(一) 主从同步

主从复制 - 数据备份, 读写分离, 手动高可用 负载均衡: 主结点只负责处理写请求, 从节点负责读请求;主从复制, 主机挂了, 我们可以手动切换从机, 还可以搭配哨兵实现自动切换, 实现高可用;需要注意的是, 在主从模式下, 假设进行同步的过程中主节点宕机了, 那么从节点此时还没有…

Ubuntu | 右上角网络图标消失,有线网络在设置中消失,虚拟机没网

目录 第一步&#xff1a;删除 NetworkManager 缓存文件第二步&#xff1a;修改 /etc/NetworkManager/NetworkManager.conf第三步&#xff1a;重启 NetworkManager第四步&#xff1a;右上角网络图标出现 参考博客&#xff1a;虚拟机没网&#xff0c;重启网络服务&#xff1a;Fai…

手机操作技巧:如何进入锁定的Android手机

被锁定在您的 Android 手机之外可能是一种令人沮丧的经历&#xff0c;尤其是当您存储了重要文件和数据时。幸运的是&#xff0c;您可以尝试几种方法来重新获得对手机的访问权限。在这篇博文中&#xff0c;我们将探讨可用于解锁锁定的 Android 手机的各种技术和工具。我们还将提…

80.游戏的分辨率修改思路与分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 上一个内容&#xff1a;79.游戏分析工具闪屏问题优化与数据被修改高亮 GAMEHACKER2.exe 工具下载地址&#xff…

Neo4j图数据库Docker部署至服务器

Neo4j图数据库Docker部署至服务器 文章目录 Neo4j图数据库Docker部署至服务器1. Neo4j介绍2. 拉取Docker镜像3. 创建容器并运行4. 导入数据&#xff08;可选&#xff09;5. 访问测试 1. Neo4j介绍 Neo4j 是一种基于图数据库管理系统&#xff0c;它专门用于存储和查询图数据结构…

Vuepress,搭建自己的技术文档

Vuepress Vuepress用于构建静态站点&#xff0c;非常适合搭建技术文档。如果手头上有开源项目&#xff0c;或者公司内部有项目需要做官网&#xff0c;且官网中大部分都是介绍、用法之类的文章。那么Vuepress是不二选择&#xff01; 我们看到的一些项目的技术文档&#xff0c;…

河北学术会议:机器视觉、图像处理与影像技术领域

第二届机器视觉、图像处理与影像技术国际会议&#xff08;MVIPIT 2024&#xff09;将于2024年9月13日-15日在中国张家口召开。MVIPIT2024聚焦机器视觉、图像处理与影像技术&#xff0c;旨在为专家、学者和研究人员提供一个国际平台&#xff0c;分享研究成果&#xff0c;讨论问题…

WebSocket可拓展业务组件搭建,无侵入实现WebSocket通信信息自定义业务消费

组件概述 面对C端产品&#xff0c;往往会携带有客户端和服务端的双端通信以实现实时交互的效果&#xff0c;但是目前HTTP1.1并不支持双端通信&#xff0c;因此&#xff0c;对于聊天室、多人实时游戏等场景&#xff0c;就需要用到一个新的通信协议&#xff1a;WebSocket。 更多…

UE5-C++入门教程(二)---编写Editor类别的自定义模型实现小球规划路线的可视化

前言 本教程将以图文教程的形式讲述如何快速入门通过C使用UE5.4进行项目编写。UE5的教程系列 第一期&#xff1a;UE5-C入门教程(一)&#xff1a;使用代码创建一个指定目标的移动小球-CSDN博客 UE5与ROS2实战->基于UE5和ROS2的激光雷达深度RGBD相机小车的仿真指南(一)—Unre…

MoneyPrinterTurbo的部署,在服务器Ubuntu22.04系统下——点动科技

在服务器Ubuntu22.04系统下&#xff0c;MoneyPrinterTurbo的部署 一、ubuntu22.04基本环境配置1.1 更换清华Ubuntu镜像源1.2 更新包列表&#xff1a;2. 安装英伟达显卡驱动2.1 使用wget在命令行下载驱动包2.2 更新软件列表和安装必要软件、依赖2.2 卸载原有驱动2.3 安装驱动2.4…

Axure高端交互元件库:助力产品与设计

用户体验&#xff08;UX&#xff09;和用户界面&#xff08;UI&#xff09;设计对于任何产品的成功都至关重要。为了在这个竞争激烈的市场中脱颖而出&#xff0c;设计师和产品开发团队需要依赖强大的工具来创造引人注目且功能丰富的交互界面。下面介绍一款Axure精心制作的"…