asp.net权限认证:OWIN实现OAuth 2.0 之客户端模式(Client Credential)

客户端模式定义

客户端使用自己的名义,而不是用户的名义,向“服务提供商” 进行认证。

 

如何理解这句话? 乍一看,定义有点拗口,刚接触的童鞋可能完全不知所云。

没关系,我们先把他的工作流程图画出来,如下:

据上图,可以得出一个大概的结论

1、用户(User)通过客户端(Client)访问受限资源(Resource)

2、因为资源受限,所以需要授权;而这个授权是Client与Authentication之间完成的,可以说跟User没有什么关系

3、根据2得出,Resource与User没有关联关系,即User不是这个Resource的Owner(所有者)

 

既然是这样,那大概可以推出这种认证的适用范围。

第一,肯定不能用作登录认证!因为登录认证后需要得到用户的一些基本信息,如昵称,头像之类,这些信息是属于User的;

第二,适用于一些对于权限要求不强的资源认证,比如:仅用于区分用户是否登录,排除匿名用户获取资源

 

新建一个资源项目:ResourceServer

 

引用owin:install-package Microsoft.Owin -Version 2.1.0

新增Startup.cs

1
2
3
4
5
6
7
8
9
10
11
[assembly: OwinStartup(typeof(ResourceServer.Startup))]
namespace ResourceServer
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

新增Startup.Auth.cs

1
2
3
4
5
6
7
8
9
10
namespace ResourceServer
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {<br>       // 这句是资源服务器认证token的关键,认证逻辑在里边封装好了,我们看不到
            app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
        }
    }
}

新增ValuesController.cs

1
2
3
4
5
6
7
8
9
10
11
namespace ResourceServer.Controllers
{
    [Authorize]
    public class ValuesController : ApiController
    {
        public string Get()
        {
            return "lanxiaoke";
        }
    }
}

 

新建认证服务项目

修改Startup.Auth.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            // Setup Authorization Server
            app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/OAuth/Token"),
                ApplicationCanDisplayErrors = true,
#if DEBUG
                AllowInsecureHttp = true,
#endif
                // Authorization server provider which controls the lifecycle of Authorization Server
                Provider = new OAuthAuthorizationServerProvider
                {
                    OnValidateClientAuthentication = ValidateClientAuthentication,
                    OnGrantClientCredentials = GrantClientCredetails
                },
 
                // Authorization code provider which creates and receives authorization code
                AuthorizationCodeProvider = new AuthenticationTokenProvider
                {
                    OnCreate = CreateAuthenticationCode,
                    OnReceive = ReceiveAuthenticationCode,
                },
 
                // Refresh token provider which creates and receives referesh token
                RefreshTokenProvider = new AuthenticationTokenProvider
                {
                    OnCreate = CreateRefreshToken,
                    OnReceive = ReceiveRefreshToken,
                }
            });
        }
 
        private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
                context.TryGetFormCredentials(out clientId, out clientSecret))
            {
                if (clientId == "123456" && clientSecret == "abcdef")
                {
                    context.Validated();
                }
            }
            return Task.FromResult(0);
        }
 
        private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
        {
            var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
            context.Validated(identity);
            return Task.FromResult(0);
        }
 
        private readonly ConcurrentDictionary<string, string> _authenticationCodes =
            new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
 
        private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
        {
            context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
            _authenticationCodes[context.Token] = context.SerializeTicket();
        }
 
        private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
        {
            string value;
            if (_authenticationCodes.TryRemove(context.Token, out value))
            {
                context.DeserializeTicket(value);
            }
        }
 
        private void CreateRefreshToken(AuthenticationTokenCreateContext context)
        {
            context.SetToken(context.SerializeTicket());
        }
 
        private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
        {
            context.DeserializeTicket(context.Token);
        }
    }

自此,认证服务项目算是建好了,因为对于客户端模式,认证服务器只需要返回token

 

新增Client项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void Main(string[] args)
   {
       var authorizationServerUri = new Uri("http://localhost:8270/");
       var authorizationServerDescription = new AuthorizationServerDescription
       {
           TokenEndpoint = new Uri(authorizationServerUri, "OAuth/Token")
       };
 
       var client = new WebServerClient(authorizationServerDescription, "123456", "abcdef");
       var state = client.GetClientAccessToken(new[] { "scopes1", "scopes2" });
       var token = state.AccessToken;
       Console.WriteLine("Token: {0}", token);
 
       var resourceServerUri = new Uri("http://localhost:8001/");
       var httpClient = new HttpClient(client.CreateAuthorizingHandler(token));
       var values = httpClient.GetStringAsync(new Uri(resourceServerUri, "api/Values")).Result;
       Console.WriteLine("Result: {0}", values);
 
       Console.ReadKey();
   }

 

OK,Client环境搭好了,我们来运行下试试

 

认证成功!

  

asp.net权限认证系列

  1. asp.net权限认证:Forms认证
  2. asp.net权限认证:HTTP基本认证(http basic)
  3. asp.net权限认证:Windows认证
  4. asp.net权限认证:摘要认证(digest authentication)
  5. asp.net权限认证:OWIN实现OAuth 2.0 之客户端模式(Client Credential)
  6. asp.net权限认证:OWIN实现OAuth 2.0 之密码模式(Resource Owner Password Credential)
  7. asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)
  8. asp.net权限认证:OWIN实现OAuth 2.0 之简化模式(Implicit)

 

posted @   ljr忒修斯之船  阅读(4057)  评论(5编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示