IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 控制台程序httpclient使用IdentityServer4的授权码模式获取token -> 正文阅读

[网络协议]控制台程序httpclient使用IdentityServer4的授权码模式获取token

控制台程序httpclient使用IdentityServer4的授权码模式获取token


系统使用IdentityServer4做鉴权,客户端是WPF,打算使用httpclient获取授权码模式的token,现做一个控制台测试例子。

获取token代码

新建一个AuthorizationCodeLogin类

using IdentityModel;
using IdentityModel.Client;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace ClientAuthorizationCode
{
    public class AuthorizationCodeLogin
    {
        public async Task<string?> GetTokenAsync()
        {
            var webProxy = new WebProxy(new Uri("http://127.0.0.1:8080"));//代理,用burp suite进行截断调试
            var baseAddress = new Uri("https://localhost:5001");

            var cookieContainer = new CookieContainer();
            var handler = new HttpClientHandler()
            {
                //Proxy = webProxy,
                //UseProxy = true,
                UseCookies = true,
                CookieContainer = cookieContainer,
            };
            var client = new HttpClient(handler);


            var disco = await client.GetDiscoveryDocumentAsync(baseAddress.AbsoluteUri);
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
                return null;
            }

            #region 创建验证地址
            var nonce = Convert.ToBase64String(CryptoRandom.CreateRandomKey(64));
            var codeVerifier = GenerateCodeVerifier();
            var codeChallenge = GenerateCodeChallenge(codeVerifier);

            var ru = new RequestUrl(disco.AuthorizeEndpoint);
            var url = ru.CreateAuthorizeUrl(
                clientId: "apiClientCode",
                responseType: "code",
                redirectUri: "http://localhost:5002/signin-oidc",
                nonce: nonce,
                codeChallenge: codeChallenge,
                codeChallengeMethod: "S256",
                scope: "api1");

            Console.WriteLine(url);

            #endregion


            #region 获取真正的登录地址,以及登录参数和Cookie
            var response1 = await client.GetAsync(url);

            if(!response1.IsSuccessStatusCode)
            {
                Console.WriteLine("获取真正的登录地址" + response1.StatusCode);
                return null;
            }
            var result = await response1.Content.ReadAsStringAsync();

            string temp = "<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\"";
            string temp1 = "\" /><input name=\"RememberLogin\"";
            int startIndex = result.IndexOf(temp);
            int endIndex = result.IndexOf(temp1);
            int length = endIndex - startIndex - temp.Length;
            string requestVerificationToken = result.Substring(startIndex + temp.Length, length);
            Console.WriteLine(requestVerificationToken);


            string temp2 = "<input type=\"hidden\" id=\"ReturnUrl\" name=\"ReturnUrl\" value=\"";
            string temp3 = "code_challenge_method=S256";
            int startIndex1 = result.IndexOf(temp2) + temp2.Length;
            int endIndex1 = result.IndexOf(temp3);
            int length1 = endIndex1 - startIndex1 + temp3.Length;
            string returnUrl = result.Substring(startIndex1, length1).Replace("amp;", "");

            Console.WriteLine(returnUrl);
            var cookies = response1.Headers.GetValues(HeaderNames.SetCookie).ToList();

            var cookieTemp = cookies[0].Split(';');
            var cookieTemp1 = cookieTemp[0].Split('=');

            #endregion


            #region 登录,获取code
            handler.CookieContainer.Add(baseAddress, new Cookie(cookieTemp1[0], cookieTemp1[1]));
            //var client1 = new HttpClient(handler);
            var formContent = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("Username", "alice"),
                new KeyValuePair<string, string>("Password", "Pass123$"),
                new KeyValuePair<string, string>("ReturnUrl", returnUrl),
                new KeyValuePair<string, string>("button", "login"),
                new KeyValuePair<string, string>("__RequestVerificationToken", requestVerificationToken),
                new KeyValuePair<string, string>("RememberLogin", "false"),
            });

            var response = await client.PostAsync(response1.RequestMessage.RequestUri, formContent);

            Console.WriteLine(response.Headers.Location.AbsoluteUri);
            Console.WriteLine(response.IsSuccessStatusCode);
            Console.WriteLine(response.StatusCode);
            if (!(response.StatusCode == HttpStatusCode.Found))
            {
                Console.WriteLine("获取Code失败"+response.StatusCode);
                return null;
            }

            //根据自己的跳转地址截取得到Code
            string code = response.Headers.Location.AbsoluteUri.Replace("http://localhost:5002/signin-oidc?code=", "").Replace("&scope=api1", "");

            #endregion

            #region 获取Token

            var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "apiClientCode",
                ClientSecret = "secret345",
                Code = code,
                GrantType = "authorization_code",
                RedirectUri = "http://localhost:5002/signin-oidc",
                CodeVerifier = codeVerifier
            });


            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return null;
            }

            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine(tokenResponse.AccessToken);
            Console.WriteLine("\n\n");

            return tokenResponse.AccessToken;

            #endregion

    
        }


        private  string GenerateCodeVerifier()
        {
            var rng = RandomNumberGenerator.Create();

            var bytes = new byte[32];
            rng.GetBytes(bytes);

            // It is recommended to use a URL-safe string as code_verifier.
            // See section 4 of RFC 7636 for more details.
            var code_verifier = Convert.ToBase64String(bytes)
                .TrimEnd('=')
                .Replace('+', '-')
                .Replace('/', '_');

            return code_verifier;
        }

        private string GenerateCodeChallenge(string code_verifier)
        {
            var code_challenge = string.Empty;
            using (var sha256 = SHA256.Create())
            {
                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(code_verifier));
                code_challenge = Convert.ToBase64String(challengeBytes)
                    .TrimEnd('=')
                    .Replace('+', '-')
                    .Replace('/', '_');

                return code_challenge;
            }
        }
    }
}

拿到token后,访问API

为了方便测试,直接在Program.cs进行编写访问API的代码了,环境是.net 6,授权中心和API是使用IdentityServer4的官方案例,点击访问

// See https://aka.ms/new-console-template for more information


using ClientAuthorizationCode;
using IdentityModel.Client;
using Newtonsoft.Json.Linq;



AuthorizationCodeLogin authorizationCodeLogin=new AuthorizationCodeLogin();

var token= authorizationCodeLogin.GetTokenAsync().GetAwaiter().GetResult();

var apiClient = new HttpClient();
apiClient.SetBearerToken(token);

var response3 = await apiClient.GetAsync("http://localhost:6011/identity");
if (!response3.IsSuccessStatusCode)
{
    Console.WriteLine(response3.StatusCode);
}
else
{
    var content = await response3.Content.ReadAsStringAsync();
    Console.WriteLine(JArray.Parse(content));
}

Console.ReadLine();


  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 19:06:09  更:2022-03-30 19:08:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:03:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码