我的第一个微服务系列(六):将User.Api添加到网关实现认证授权

  在前面五篇博文后,我们已经实现了通过User.Identity来调用User.Api实现认证获取到token,所以我们应该将User.Api除了认证接口外的接口都添加到Api.Gateway网关中,同时也将User.Identity添加到网关中,实现外网访问统一入口。

  Ocelot很好的支持了IdentityServer4,所以在Api.Gateway中需要添加IdentityServer4和IdentityServer4.AccessTokenValidation两个Nuget包

Install-Package IdentityServer4
Install-Package IdentityServer4.AccessTokenValidation

  在Ocelot.json中添加User.Api和User.Identity的路由配置

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/user",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 63679
        }
      ],
      "UpstreamPathTemplate": "/user",
      "UpstreamHttpMethod": [ "Get", "Patch" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Finbook",
        "AllowedScopes": [ "user_api" ]
      }
    },
    {
      "DownstreamPathTemplate": "/api/user/baseinfo/{userId}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 63679
        }
      ],
      "UpstreamPathTemplate": "/user/baseinfo/{userId}",
      "UpstreamHttpMethod": [ "Get" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Finbook",
        "AllowedScopes": [ "user_api" ]
      }
    },
    {
      "DownstreamPathTemplate": "/api/user/tags",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 63679
        }
      ],
      "UpstreamPathTemplate": "/user/tags",
      "UpstreamHttpMethod": [ "Get", "Put" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Finbook",
        "AllowedScopes": [ "user_api" ]
      }
    },
    {
      "DownstreamPathTemplate": "/api/user/search",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 63679
        }
      ],
      "UpstreamPathTemplate": "/user/search",
      "UpstreamHttpMethod": [ "Post" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Finbook",
        "AllowedScopes": [ "user_api" ]
      }
    },
    {
      "DownstreamPathTemplate": "/connect/{catchAll}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 56424
        }
      ],
      "UpstreamPathTemplate": "/connect/{catchAll}",
      "UpstreamHttpMethod": [ "Post" ]
    },
    {
      "DownstreamPathTemplate": "/.well-known/{catchAll}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 56424
        }
      ],
      "UpstreamPathTemplate": "/.well-known/{catchAll}",
      "UpstreamHttpMethod": [ "Get" ]
    }
  ],
    "GlobalConfiguration": {
        "BaseUrl": "http://localhost"
    }
}

  可以看到User.Api的路由都添加了 AuthenticationOptions 选项来授权,添加完配置后需要在Startup中注入IdentityServer

var authenticationProviderKey = "Finbook";

services.AddAuthentication()
    .AddIdentityServerAuthentication(authenticationProviderKey, options=> {
        options.Authority = "http://localhost:56424"; //User.Identity服务器的Url
        options.ApiName = "gateway_api";
        options.SupportedTokens = SupportedTokens.Both;
        options.ApiSecret = "secret";
        options.RequireHttpsMetadata = false;
    });

  启动项目,通过postman可以测试拿到token

 

   如果未携带token访问想要获取用户信息将返回401

 

   将User.Api添加到网关后,如果我们需要获取当前用户信息该怎么办呢,这时候已经不像以前单体架构可以使用session来保存当前用户信息了,我们需要使用Asp.Net Core Identity 。

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.RequireHttpsMetadata = false;
        options.Audience = "user_api";
        options.Authority = "http://localhost"; // Api.Gateway网关Url
    });
app.UseAuthentication();

  可以在BaseController中获取到当前用户信息

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using User.API.Dtos;

namespace User.API.Controllers
{
    public class BaseController : Controller
    {
        protected UserIdentity UserIdentity
        {
            get
            {
                return new UserIdentity {
                    UserId = Convert.ToInt32(User.Claims.FirstOrDefault(c => c.Type == "sub").Value),
                    Name = User.Claims.FirstOrDefault(c => c.Type == "name").Value,
                    Company = User.Claims.FirstOrDefault(c=>c.Type == "company").Value,
                    Title = User.Claims.FirstOrDefault(c=>c.Type == "title").Value,
                    Avatar = User.Claims.FirstOrDefault(c=>c.Type == "avatar").Value
                };
            }
        }
    }
}

 

posted @ 2020-12-07 23:27  柠檬笔记  阅读(490)  评论(0编辑  收藏  举报