代码改变世界

OAuth2认证和授权:ResourceOwnerPassword认证

  糯米粥  阅读(2081)  评论(0编辑  收藏  举报

ResourceOwnerPassword在 ClientCredentials认证上新增了用户名和密码

 

但通过RequestPasswordTokenAsync获取不到refresh_token,不知道为什么

复制代码
using IdentityModel;
using IdentityModel.Client;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Http;
using System.Text;

namespace PassWord
{
    /// <summary>
    /// 客户端模式,请求授权服务器获取token,请求资源服务器获取资源
    /// 依赖包:IdentityModel
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            string Authority = "http://localhost:5003";
            string ApiResurce = "http://localhost:5002/";
            var tokenCliet = new HttpClient()
            {
                BaseAddress = new Uri(ApiResurce)
            };

            /*
             这样做的目的是:
             资源服务器会去授权服务器认证,所以在客户端可以先判断下授权服务器是否挂了
             */
            DiscoveryCache _cache = new DiscoveryCache(Authority);
            var disco1 = _cache.GetAsync().Result;
            if (disco1.IsError) throw new Exception(disco1.Error);
            //或者
            var disco = tokenCliet.GetDiscoveryDocumentAsync(Authority).Result;
            if (disco.IsError) throw new Exception(disco.Error);


            var response = tokenCliet.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "userinfo_pwd",
                ClientSecret = "secret",
                //GrantType = "password",
                UserName = "cnblogs",
                Password = "123",
                Scope = "apiInfo.read_full"
            }).Result;

            if (response.IsError) throw new Exception(response.Error);

            var token = response.AccessToken;

            //把token,Decode
            if (response.AccessToken.Contains("."))
            {
                //Console.WriteLine("\nAccess Token (decoded):");
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("\nAccess Token (decoded):");
                Console.ResetColor();

                var parts = response.AccessToken.Split('.');
                var header = parts[0];
                var claims = parts[1];

                Console.WriteLine(JObject.Parse(Encoding.UTF8.GetString(Base64Url.Decode(header))));
                Console.WriteLine(JObject.Parse(Encoding.UTF8.GetString(Base64Url.Decode(claims))));
            }
            //设置请求的Token
            tokenCliet.SetBearerToken(token);
            //请求并返回字符串
            var apiResource1 = tokenCliet.GetStringAsync("identity").Result;
            var userinfo = tokenCliet.GetStringAsync("identity/userinfo").Result;

            var j = JObject.Parse(userinfo);
            //或者
            var getVal = tokenCliet.GetAsync("api/values").Result;
            if (getVal.IsSuccessStatusCode)
            {
                Console.WriteLine(getVal.Content.ReadAsStringAsync().Result);
            }
            Console.ReadLine();
        }
    }
}
复制代码

 

但自己写一个请求方式,是可以获取到的

HttpClientHepler帮助类,参考网上

复制代码
  public class HttpClientHepler
    {
        string _url;
        public string Url
        {
            get
            {
                return _url;
            }

            set
            {
                _url = value;
            }
        }

        public HttpClientHepler(string url)
        {
            Url = url;
        }

        public async Task GetAsync(string queryString, Action<HttpRequestHeaders> addHeader,
            Action<string> okAction = null,
            Action<HttpResponseMessage> faultAction = null, Action<Exception> exAction = null)
        {
            using (HttpClient client = new HttpClient())
            {
                addHeader(client.DefaultRequestHeaders);
                using (HttpResponseMessage response = await client.GetAsync(Url + "?" + queryString))
                {
                    try
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            okAction(await response.Content.ReadAsStringAsync());
                        }
                        else
                        {
                            faultAction?.Invoke(response);
                        }
                    }
                    catch (Exception ex)
                    {
                        exAction?.Invoke(ex);
                    }
                }
            }
        }

        public async Task PostAsync(string queryString, string content, Action<HttpContentHeaders> addHeader,
            Action<string> okAction = null,
            Action<HttpResponseMessage> faultAction = null, Action<Exception> exAction = null)
        {
            using (HttpClient client = new HttpClient())
            {
                using (HttpContent httpContent = new StringContent(content))
                {
                    addHeader(httpContent.Headers);
                    using (HttpResponseMessage response = await client.PostAsync(Url + "?" + queryString, httpContent))
                    {
                        try
                        {
                            if (response.IsSuccessStatusCode)
                            {
                                okAction(await response.Content.ReadAsStringAsync());
                            }
                            else
                            {
                                faultAction?.Invoke(response);
                            }
                        }
                        catch (Exception ex)
                        {
                            exAction?.Invoke(ex);
                        }
                    }
                }
            }
        }


    }
复制代码

 

 

黄色标记部分是新增代码,运行获取成功

 

复制代码
   static void Main(string[] args)
        {
            string Authority = "http://localhost:5003";
            string ApiResurce = "http://localhost:5002/";
            var tokenCliet = new HttpClient()
            {
                BaseAddress = new Uri(ApiResurce)
            };



            /*
             这样做的目的是:
             资源服务器会去授权服务器认证,所以在客户端可以先判断下授权服务器是否挂了
             */
            DiscoveryCache _cache = new DiscoveryCache(Authority);
            var disco1 = _cache.GetAsync().Result;
            if (disco1.IsError) throw new Exception(disco1.Error);
            //或者
            var disco = tokenCliet.GetDiscoveryDocumentAsync(Authority).Result;
            if (disco.IsError) throw new Exception(disco.Error);


            //获取token
            var AccessToken = "";
            var RefreshToken = "";
            //通过code获取AccessToken
            var client1 = new HttpClientHepler(disco.TokenEndpoint);
            client1.PostAsync(null,
                "client_id=userinfo_pwd" +
                "&client_secret=secret" +
                "&grant_type=password" +
                "&username=cnblogs" +
                "&password=123",
                hd => hd.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded"),
                rtnVal =>
                {
                    var jsonVal = JsonConvert.DeserializeObject<dynamic>(rtnVal);
                    AccessToken = jsonVal.access_token;
                    RefreshToken = jsonVal.refresh_token;
                }).Wait();

            //用RefreshToken 刷新AccessToken
            var responseToken = tokenCliet.RequestRefreshTokenAsync(new RefreshTokenRequest
            {
                Address = disco.TokenEndpoint,

                ClientId = "userinfo_pwd",
                ClientSecret = "secret",
                RefreshToken = RefreshToken
            }).Result;



            var response = tokenCliet.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "userinfo_pwd",
                ClientSecret = "secret",
                //GrantType = "password",
                UserName = "cnblogs",
                Password = "123",
                Scope = "apiInfo.read_full"
            }).Result;

            if (response.IsError) throw new Exception(response.Error);

            var token = response.AccessToken;

            //把token,Decode
            if (response.AccessToken.Contains("."))
            {
                //Console.WriteLine("\nAccess Token (decoded):");
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("\nAccess Token (decoded):");
                Console.ResetColor();

                var parts = response.AccessToken.Split('.');
                var header = parts[0];
                var claims = parts[1];

                Console.WriteLine(JObject.Parse(Encoding.UTF8.GetString(Base64Url.Decode(header))));
                Console.WriteLine(JObject.Parse(Encoding.UTF8.GetString(Base64Url.Decode(claims))));
            }
            //设置请求的Token
            tokenCliet.SetBearerToken(token);
            //请求并返回字符串
            var apiResource1 = tokenCliet.GetStringAsync("identity").Result;
            var userinfo = tokenCliet.GetStringAsync("identity/userinfo").Result;

            var j = JObject.Parse(userinfo);
            //或者
            var getVal = tokenCliet.GetAsync("api/values").Result;
            if (getVal.IsSuccessStatusCode)
            {
                Console.WriteLine(getVal.Content.ReadAsStringAsync().Result);
            }
            Console.ReadLine();
        }
复制代码

 

 

 

 用RefreshToken刷新也成功

 

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
历史上的今天:
2014-02-02 一个简单的网页选项卡
'
点击右上角即可分享
微信分享提示