ocelot+IdentityServer认证

IdentityServer4

IdentityServer4是用于ASP.NET Core的OpenID Connect和OAuth 2.0框架。

具体大家可以自己搜索,网上很多。我不想写的就推荐别人的。

IdentityServer4(一):概念及基本介绍_江浙沪柯蓝的博客-CSDN博客_identityserver4

IdentityServer4学习及简单使用 - Vincent-yuan - 博客园 (cnblogs.com)

开源地址:IdentityServer/IdentityServer4: OpenID Connect and OAuth 2.0 Framework for ASP.NET Core (github.com)

新版升级

前一篇简单提了一下,今天我整理了一下,IdentityServer4开源已经说明,项目迁移升级了。

我使用了网页翻译。如下:

新版地址:DuendeSoftware/IdentityServer: The most flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core (github.com)

Duende IdentityServer


IdentityServer4的新版本,这里按照以前的方式简单介绍一下使用。

认证服务器,创建WebApi项目,nuget引入Duende.IdentityServer

其实Duende.IdentityServer.AspNetIdentity时与web的集成,有兴趣的自己研究,我没有使用。

创建配置类,可以照搬IdentityServer4的,


using Duende.IdentityServer.Models;
using Duende.IdentityServer.Test;

namespace OcelotIdentityServer4
{
    /// <summary>
    /// 路由 /connect/token post方式 body参数client_id,client_secret,grant_type 
    /// </summary>
    public class Config
    {
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>()
            {
                new ApiResource("api", "My Api"){ Scopes ={"api"} }
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>()
            {
                new Client()
                {
                    ClientId = "ro.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                    // AccessTokenType = AccessTokenType.Reference,
                    ClientSecrets =
                    {
                        new Secret("123456".Sha256())
                    },
                    AllowedScopes =
                    {
                        "api"
                    },
                  Claims =new List<ClientClaim>()
                  {
                   new ClientClaim(IdentityModel.JwtClaimTypes.Role,"admin"),
                    new ClientClaim(IdentityModel.JwtClaimTypes.NickName,"江北"),
                     new ClientClaim("Email","**********@163.com"),
               }
                }
            };
        }

        public static IEnumerable<ApiScope> ApiScopes =>
            new ApiScope[] { new ApiScope("api") };

        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile()
            };
        }

        public static IEnumerable<TestUser> Users()
        {
            return new[]
            {
                new TestUser
                {
                    SubjectId = "",
                    Username = "mail@qq.com",
                    Password = "password"
                }
            };
        }
    }
}

建立测试类

using Duende.IdentityServer.Models;
using Duende.IdentityServer.Validation;
using System.Security.Claims;

namespace OcelotIdentityServer
{
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //根据context.UserName和context.Password与数据库的数据做校验,判断是否合法
            if (context.UserName == "yzk" && context.Password == "123")
            {
                context.Result = new GrantValidationResult(
                subject: context.UserName,
                authenticationMethod: "custom",
                claims: new Claim[] { new Claim("Name", context.UserName), new Claim("UserId", "111"), new Claim("RealName", "杨中科"), new Claim("Email", "yzk365@qq.com") });
            }
            else
            {
                //验证失败
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
            }
        }
    }
}

using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;

namespace OcelotIdentityServer
{
    public class ProfileService : IProfileService
    {
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var claims = context.Subject.Claims.ToList();
            context.IssuedClaims = claims.ToList();
        }
        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }
}

最后加入

builder.Services.AddIdentityServer(options =>
{
    options.EmitStaticAudienceClaim = true;
})
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiScopes(Config.ApiScopes)
    .AddInMemoryClients(Config.GetClients())
    .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
            .AddProfileService<ProfileService>();

设置好项目绑定的IP端口(19138)

WebApi项目中使用

nuget引入上面相同

program.cs加入

//添加鉴权认证
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
                .AddJwtBearer(options =>
                {
                    //鉴权中心服务地址
                    options.Authority = "https://localhost:19138";
                    options.RequireHttpsMetadata = false;
                    options.Audience = "api";
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false
                    };
                });

还得继续加入

app.UseAuthentication();

创建一个控制器

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace ConsulForProject.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
       {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
        [Authorize]
        [HttpGet]
        public IEnumerable<WeatherForecast> Getm()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

这样就可以用postman工具测试了

启动认证中心和api项目。

访问https://localhost:19138/connect/token 获取token

访问api:

ocelot集成

项目引入

program.cs加入

//添加鉴权认证
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
                .AddJwtBearer("AuthKey", options =>
                {
                    //鉴权中心服务地址
                    options.Authority = "https://localhost:19138";
                    options.RequireHttpsMetadata = false;
                    options.Audience = "api";
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false
                    };
                });

配置文件

测试ocelot

扩展 建立登录项目

创建一个login项目,在其中登录并且获取token.

项目里面我用了EF dbfirst方式查询数据库。

数据库:mysql

我不详细写EF使用了。这里推荐博客。

.net 连接MySql数据库 + 使用Microsoft.EntityFrameworkCore.Design自动生成实体类 + 使用EFCore操作数据库_程序猿想成程序狮的博客-CSDN博客_microsoft.entityframeworkcore.design

完成后

创建登录控制器

using LoginService.Repository;
using Microsoft.AspNetCore.Mvc;

namespace LoginService.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        private readonly ILogger<LoginController> _logger;
        private IConfiguration _IConfiguration;
        private readonly MytestContext _context;

        public LoginController(ILogger<LoginController> logger, IConfiguration configuration, MytestContext context)
        {
            _logger = logger;
            _IConfiguration = configuration;
            _context = context;
        }
        [HttpPost]
        public async Task<ActionResult> RequestToken(RequestTokenParam model)
        {
            this._logger.LogInformation($"{this._IConfiguration["port"]}- Login Token!");
            var usr = _context.Users.FirstOrDefault(user => user.Username == model.username);
            
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict["client_id"] = "ro.client";
                dict["client_secret"] = "123456";
                dict["grant_type"] = "password";
                dict["username"] = usr.Username;
                dict["password"] = usr.Password;
                //由登录服务器向IdentityServer发请求获取Token
                using (HttpClient http = new HttpClient())
                using (var content = new FormUrlEncodedContent(dict))
                {
                    var msg = await http.PostAsync("https://localhost:19138/connect/token", content);
                    string result = await msg.Content.ReadAsStringAsync();
                    return Content(result, "application/json");
                }
            
        }
    }
}
namespace LoginService
{
    public class RequestTokenParam
    {
        public string? username { get; set; }
        public string? password { get; set; }
    }
}

使用postman测试

这样通过登录返回token,就可以继续访问了。

今天就补充这么多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值