精华内容
下载资源
问答
  • WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证

    WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证

    参考文章:

    (1)WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证

    (2)https://www.cnblogs.com/codelir/p/9977667.html


    备忘一下。


    展开全文
  • 刚开始开发接口的时候,为了省事就没有做权限验证,想着等逻辑都调通以后再回过头来统一加上去。结果等功能开发结束,发现每个接口里面都加上五到十行的权限验证功能就有点坑了,这么多的重复代码怎么给它再简化一下...

      最近在使用WEBAPI项目开发接口,主要是用于跟安卓与IOS开发的同事对接。刚开始开发接口的时候,为了省事就没有做权限验证,想着等逻辑都调通以后再回过头来统一加上去。结果等功能开发结束,发现每个接口里面都加上五到十行的权限验证功能就有点坑了,这么多的重复代码怎么给它再简化一下呢?
      在一个技术群里发问之后,有个朋友截了张图,内容是在接口上方声明一个属性,然后在属性里面进行验证。这个是不错的想法,以前我见过用这种方法的,但具体含义不明。正好这次能用上,就自己编写了一个属性。
      基本思路有三步:1、确定在哪里执行验证;2、获取APP传入的参数;3、根据参数进行权限验证;4、如果权限验证不通过就不再执行接口中的功能。
      第1步很容易就实现了,在我敲完“public override”后,界面就提示出了可以重写的方法,一个个的看过注释后,发现OnActionExecuting是接口内容执行前执行的代码,于是确定要在这里面写。
      第2步的难度也不大,程序运行起来之后,把OnActionExecuting参数列表的各项内容打开看了下,结果发现传入参数放在ActionArguments中,于是从中截取出了reqeust参数(即我自定义的传入参数实体名),里面存有APP同事传给我的各项信息。
      第3步就更简单了,就是把参数拿出来跟数据库作下对照。
      第4步有点坑,因为不知道怎么停止执行接口功能。于是先使用了传统的HttpContext.Current.Response.End,结果发现没用。然后去百度了半天接口拦截,一直没看出个所以然来。最后突然灵光一现,如果把请求的返回状态直接声明为完成,会不会拦截成功?于是这样调试了一下,果然奏效。

    //属性代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Http.Filters;
    using System.Web;
    using System.Net.Http;//该DLL需要手动加入,在系统框架中

        public class ApiAuthAttribute : ActionFilterAttribute
        {
            private static DalUser userData = new DalUser();
            /// <summary>
            /// 权限验证,通过为true,否则为false
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            private static bool AuthValid(string userId)
            {
                if (string.IsNullOrEmpty(userId))
                {
                    return false;
                }
                var objUser = userData.GetUserById(userId);
                if (objUser == null || string.IsNullOrEmpty(objUser.ID))
                {
                    return false;
                }
                return true;
            }

            public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)//执行方法前的操作
            {
                BaseResponseEntity response = new BaseResponseEntity();
                response.Code = (int)ResponseCode.ValidError;
                response.Message = "权限验证失败";
                string result = JsonConvert.SerializeObject(response);

                if (actionContext.ActionArguments == null || actionContext.ActionArguments.Count == 0)//没有传入用户信息
                {
                    HttpContext.Current.Response.Write(result);
                    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);//OK为请求结束,拦截其余的执行
                }
                string userId = string.Empty;
                if (actionContext.ActionArguments.ContainsKey("request"))//参数列表中包含request
                {
                    BaseRequestEntity request = (BaseRequestEntity)actionContext.ActionArguments["request"];
                    if (request == null)
                    {
                        HttpContext.Current.Response.Write(result);
                        actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                    }
                    userId = request.userId;
                }

                else

                {

                        HttpContext.Current.Response.Write(result);
                        actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);

                }   
                if (!AuthValid(userId))
                {
                    HttpContext.Current.Response.Write(result);
                    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                }
            }

    使用拦截时的代码:
    [ApiAuthAttribute]
    public string GetResult(BaseRequest request)
    {

    }

    随后在群里问了一下,有朋友说这是AOP的实现方法,管他什么P呢,好用就行了。

    展开全文
  • web api 单点登录(SSO) 权限验证

    千次阅读 2013-06-11 13:16:02
    本文介绍利用web api实现单点登录,具体原理请看http://www.cnblogs.com/Work-hard/archive/2013/04/10/3011589.html,下面主要介绍相关代码: 分站代码: using System;using System.Collections.Generic;using ...

    本文介绍利用web api实现单点登录,具体原理请看http://www.cnblogs.com/Work-hard/archive/2013/04/10/3011589.html,下面主要介绍相关代码:

    分站代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Web.Mvc;
    using System.Net.Http;

    namespace MvcApplication2.Controllers
    {
    public class HomeController : Controller
    {
    public class infoMassege
    {
    public string webName { get; set; }
    public string[] message { get; set; }
    }
    public ActionResult Index()
    {
    //令牌验证结果
    if (Request.QueryString["Token"] != null)
    {
    //持有令牌
    string tokenValue = Request.QueryString["Token"];
    HttpCookie tokenCookie = new HttpCookie("Token");
    tokenCookie.Values.Add("Value", tokenValue);
    tokenCookie.Expires = DateTime.Now.Add(new TimeSpan(24, 0, 0));
    tokenCookie.Path = "/";
    Response.AppendCookie(tokenCookie);

    if (Session["Info"]==null)
    {
    getInfo(tokenValue);
    }
    }
    else if (Request.Cookies["Token"]!= null)
    {
    string tokenValue = Convert.ToString(Request.Cookies["Token"].Value);
    if (Session["Info"] == null)
    {
    getInfo(tokenValue);
    }
    }
    else
    {
    //未持有令牌
    Response.Redirect("http://localhost:4213/?BackURL=" + Server.UrlEncode(Request.Url.AbsoluteUri));
    }
    return View();
    }

    public void getInfo(string tokenValue)
    { //客户端调用Web api
    System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
    client.BaseAddress = new Uri("http://localhost:4213/");
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
    HttpResponseMessage response = client.GetAsync("api/Login/?token=" + tokenValue).Result;
    if (response.IsSuccessStatusCode)
    {
    infoMassege info = response.Content.ReadAsAsync<infoMassege>().Result;
    string[] a = info.message;
    System.Web.HttpContext.Current.Session["Info"] = a;
    System.Web.HttpContext.Current.Session.Timeout = 1;
    }
    else
    {
    Response.Redirect("http://localhost:4213/?BackURL=" + Server.UrlEncode(Request.Url.AbsoluteUri));
    return;
    }
    }
    }
    }

     

    主站代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;
    using System.Web.Http;
    using SSO.Passport.Class;
    using System.Data;

    namespace MvcApplication1.Controllers
    {
    public class LoginController : ApiController
    {
    public class infoMassege
    {
    public string webName { get; set; }
    public string[] message { get; set; }
    //public string webName = "a";
    //public string[] message = { "user", "admin", "tuorist" };
    };
    HttpResponseMessage response;
    LoginController()
    {
    response = new HttpResponseMessage();
    }
    [HttpPost]
    public HttpResponseMessage Post()
    {

    //摸拟用户登录验证(帐号、密码于web.config中)
    //真实环境此处应通过数据库进行验证
    //if (this.txtAccount.Text == System.Configuration.ConfigurationManager.AppSettings["acc"] && this.txtPassport.Text == System.Configuration.ConfigurationManager.AppSettings["pas"])
    //{
    //产生令牌
    string tokenValue = this.getGuidString();
    HttpContext.Current.Cache.Insert(tokenValue+"a", tokenValue, null, DateTime.Now.AddMinutes(3), TimeSpan.Zero);

    //产生主站凭证
    CreateInfo(tokenValue);
    response = Request.CreateResponse(HttpStatusCode.OK, @"{""tokenValue"":""" + tokenValue+@"""}");
    return response;
    }
    //产生主站凭证
    private void CreateInfo(string tokenValue)
    {
    infoMassege info = new infoMassege();
    info.message = new string[] { "user", "admin", "tuorist" };
    info.webName = "a";
    if (HttpContext.Current.Cache[tokenValue] == null)
    {
    HttpContext.Current.Cache.Insert(tokenValue, info, null, DateTime.Now.AddMinutes(1),TimeSpan.Zero);
    }
    //System.Web.Caching.Cache c = HttpContext.Current.Cache;
    //CacheManager.TokenInsert(tokenValue, info, DateTime.Now.AddMinutes(100));
    }

    [HttpGet]
    public HttpResponseMessage getCache(string token)
    {
    if (HttpContext.Current.Cache[token + "a"] != null)
    {
    infoMassege proof = new infoMassege();
    proof = (infoMassege)HttpContext.Current.Cache[token];
    if (proof != null)
    {
    response = Request.CreateResponse(HttpStatusCode.OK, proof);
    }
    else
    {
    CreateInfo(token);
    getCache(token);
    }
    }
    else
    {
    response = Request.CreateResponse(HttpStatusCode.Forbidden);
    }
    return response;
    }


    /// <summary>
    /// 产生绝对唯一字符串,用于令牌
    /// </summary>
    /// <returns></returns>
    private string getGuidString()
    {
    return Guid.NewGuid().ToString().ToUpper();
    }
    }
    }


    <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
    展开全文
  • Ocelot统一权限验证

    千次阅读 2017-12-11 00:00:00
    前一篇,我们创建了OcelotGateway网关项目,DemoAAPI项目,DemoBAPI项目,为了验证用户并分发Token,现在还需要添加AuthenticationAPI项目,也是asp.net core web api项目,整体思路是,当用户首次请求(Request)时...

    Ocelot作为网关,可以用来作统一验证,接上一篇博客Ocelot网关,我们继续

    前一篇,我们创建了OcelotGateway网关项目,DemoAAPI项目,DemoBAPI项目,为了验证用户并分发Token,现在还需要添加AuthenticationAPI项目,也是asp.net core web api项目,整体思路是,当用户首次请求(Request)时web服务,网关会判断本请求有无Token,并是否正确,如果没有或不正确,就会反回401 Unauthorized;如果请求调用登录,正确输入用户名或密码,AuthenticationAPI会验证并分发Token;当客户端带上Token再次访问web服务时,网关就会放过本请求,当请求到达web服务时,web服务要对本Token进行授权验证,如果有访问请求的地址,会成功返回应答,负责会提示没有权验,所以只要具有正确的Token,应答返回都是200 OK,因为Token正确,只是没有权限访问请求的内容。
    下面创建最重要的一个项目Ocelot.JWTAuthorizePolicy,选.NET Standard的类库作为项目模板创建本项目,本项目的作用是为网关项目(OcelotGateway),web服务项目(DemoAAPI和DemoBAPI),和AuthenticationAPI提供注入JWT或自定义策略的API,关于自定义策略,可参考(http://www.cnblogs.com/axzxs2001/p/7530929.html)
    本项目中的组成部分:
    Permission.cs

    namespace Ocelot.JWTAuthorizePolicy

    {

    /// <summary>

    /// 用户或角色或其他凭据实体

    /// </summary>

    public class Permission

    {

    /// <summary>

    /// 用户或角色或其他凭据名称

    /// </summary>

    public virtual string Name

    { get; set; }

    /// <summary>

    /// 请求Url

    /// </summary>

    public virtual string Url

    { get; set; }

    }

    }


    PermissionRequirement.cs


    using Microsoft.AspNetCore.Authorization;

    using Microsoft.IdentityModel.Tokens;

    using System;

    using System.Collections.Generic;


    namespace Ocelot.JWTAuthorizePolicy

    {

    /// <summary>

    /// 必要参数类

    /// </summary>

    public class PermissionRequirement : IAuthorizationRequirement

    {

    /// <summary>

    /// 无权限action

    /// </summary>

    public string DeniedAction { get; set; }


    /// <summary>

    /// 认证授权类型

    /// </summary>

    public string ClaimType { internal get; set; }

    /// <summary>

    /// 请求路径

    /// </summary>

    public string LoginPath { get; set; } = "/Api/Login";

    /// <summary>

    /// 发行人

    /// </summary>

    public string Issuer { get; set; }

    /// <summary>

    /// 订阅人

    /// </summary>

    public string Audience { get; set; }

    /// <summary>

    /// 过期时间

    /// </summary>

    public TimeSpan Expiration { get; set; }

    /// <summary>

    /// 签名验证

    /// </summary>

    public SigningCredentials SigningCredentials { get; set; }


    /// <summary>

    /// 构造

    /// </summary>

    /// <param name="deniedAction">无权限action</param>

    /// <param name="userPermissions">用户权限集合</param>


    /// <summary>

    /// 构造

    /// </summary>

    /// <param name="deniedAction">拒约请求的url</param> 

    /// <param name="claimType">声明类型</param>

    /// <param name="issuer">发行人</param>

    /// <param name="audience">订阅人</param>

    /// <param name="signingCredentials">签名验证实体</param>

    public PermissionRequirement(string deniedAction, string claimType, string issuer, string audience, SigningCredentials signingCredentials, TimeSpan expiration)

    {

    ClaimType = claimType;

    DeniedAction = deniedAction; 

    Issuer = issuer;

    Audience = audience;

    Expiration = expiration;

    SigningCredentials = signingCredentials;

    }

    }

    }


    PermissionHandler.cs

    using Microsoft.AspNetCore.Authentication;

    using Microsoft.AspNetCore.Authentication.JwtBearer;

    using Microsoft.AspNetCore.Authorization;

    using Microsoft.Extensions.DependencyInjection;

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Security.Claims;

    using System.Threading.Tasks;


    namespace Ocelot.JWTAuthorizePolicy

    {

    /// <summary>

    /// 权限授权Handler

    /// </summary>

    public class PermissionHandler : AuthorizationHandler<PermissionRequirement>

    {

    /// <summary>

    /// 验证方案提供对象

    /// </summary>

    public IAuthenticationSchemeProvider Schemes { get; set; }

    /// <summary>

    /// 用户权限集合

    /// </summary>

    List<Permission> _permissions;

    /// <summary>

    /// 构造

    /// </summary>

    /// <param name="schemes"></param>

    public PermissionHandler(IAuthenticationSchemeProvider schemes, List<Permission> permissions=null)

    {

    Schemes = schemes;

    _permissions = permissions;

    }


    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)

    {

    //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息

    var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext;

    //请求Url

    var questUrl = httpContext.Request.Path.Value.ToLower();

    //判断请求是否停止

    var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();

    foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())

    {

    var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler;

    if (handler != null && await handler.HandleRequestAsync())

    {

    context.Fail();

    return;

    }

    }

    //判断请求是否拥有凭据,即有没有登录

    var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();

    if (defaultAuthenticate != null)

    {

    var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);

    //result?.Principal不为空即登录成功

    if (result?.Principal != null)

    {

    httpContext.User = result.Principal;

    //权限中是否存在请求的url

    if (_permissions!=null&&_permissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0)

    {

    var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == requirement.ClaimType).Value;

    //验证权限

    if (_permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() == 0)

    {

    //无权限跳转到拒绝页面 

    httpContext.Response.Redirect(requirement.DeniedAction);

    context.Succeed(requirement);

    return;

    }

    }

    //判断过期时间

    if (DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration).Value) >= DateTime.Now)

    {

    context.Succeed(requirement);

    }

    else

    {

    context.Fail();

    }

    return;

    }

    }

    //判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败

    if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST")

    || !httpContext.Request.HasFormContentType))

    {

    context.Fail();

    return;

    }

    context.Succeed(requirement);

    }

    }

    }

    JwtToken.cs



    using System;

    using System.IdentityModel.Tokens.Jwt;

    using System.Security.Claims;


    namespace Ocelot.JWTAuthorizePolicy

    {

    /// <summary>

    /// JWTToken生成类

    /// </summary>

    public class JwtToken

    {

    /// <summary>

    /// 获取基于JWT的Token

    /// </summary>

    /// <param name="username"></param>

    /// <returns></returns>

    public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement)

    {

    var now = DateTime.UtcNow;

    var jwt = new JwtSecurityToken(

    issuer: permissionRequirement.Issuer,

    audience: permissionRequirement.Audience,

    claims: claims,

    notBefore: now,

    expires: now.Add(permissionRequirement.Expiration),

    signingCredentials: permissionRequirement.SigningCredentials

    );

    var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

    var responseJson = new

    {

    Status = true,

    access_token = encodedJwt,

    expires_in = permissionRequirement.Expiration.TotalMilliseconds,

    token_type = "Bearer"

    };

    return responseJson;

    }

    }

    }

    OcelotJwtBearerExtension.cs,本类型中的方法分别用于网关,web服务,和验证服务,请参看注释


    using Microsoft.AspNetCore.Authentication;

    using Microsoft.AspNetCore.Authorization;

    using Microsoft.Extensions.DependencyInjection;

    using Microsoft.IdentityModel.Tokens;

    using System;

    using System.Collections.Generic;

    using System.Security.Claims;

    using System.Text;


    namespace Ocelot.JWTAuthorizePolicy

    {

    /// <summary>

    /// Ocelot下JwtBearer扩展

    /// </summary>

    public static class OcelotJwtBearerExtension

    {

    /// <summary>

    /// 注入Ocelot下JwtBearer,在ocelot网关的Startup的ConfigureServices中调用

    /// </summary>

    /// <param name="services">IServiceCollection</param>

    /// <param name="issuer">发行人</param>

    /// <param name="audience">订阅人</param>

    /// <param name="secret">密钥</param>

    /// <param name="defaultScheme">默认架构</param>

    /// <param name="isHttps">是否https</param>

    /// <returns></returns>

    public static AuthenticationBuilder AddOcelotJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, bool isHttps = false)

    {

    var keyByteArray = Encoding.ASCII.GetBytes(secret);

    var signingKey = new SymmetricSecurityKey(keyByteArray);

    var tokenValidationParameters = new TokenValidationParameters

    {

    ValidateIssuerSigningKey = true,

    IssuerSigningKey = signingKey,

    ValidateIssuer = true,

    ValidIssuer = issuer,//发行人

    ValidateAudience = true,

    ValidAudience = audience,//订阅人

    ValidateLifetime = true,

    ClockSkew = TimeSpan.Zero,

    RequireExpirationTime = true,

    };

    return services.AddAuthentication(options =>

    {

    options.DefaultScheme = defaultScheme;

    })

    .AddJwtBearer(defaultScheme, opt =>

    {

    //不使用https

    opt.RequireHttpsMetadata = isHttps;

    opt.TokenValidationParameters = tokenValidationParameters;

    });

    }


    /// <summary>

    /// 注入Ocelot jwt策略,在业务API应用中的Startup的ConfigureServices调用

    /// </summary>

    /// <param name="services">IServiceCollection</param>

    /// <param name="issuer">发行人</param>

    /// <param name="audience">订阅人</param>

    /// <param name="secret">密钥</param>

    /// <param name="defaultScheme">默认架构</param>

    /// <param name="policyName">自定义策略名称</param>

    /// <param name="deniedUrl">拒绝路由</param>

    /// <param name="isHttps">是否https</param>

    /// <returns></returns>

    public static AuthenticationBuilder AddOcelotPolicyJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, string policyName, string deniedUrl, bool isHttps = false)

    {


    var keyByteArray = Encoding.ASCII.GetBytes(secret);

    var signingKey = new SymmetricSecurityKey(keyByteArray);

    var tokenValidationParameters = new TokenValidationParameters

    {

    ValidateIssuerSigningKey = true,

    IssuerSigningKey = signingKey,

    ValidateIssuer = true,

    ValidIssuer = issuer,//发行人

    ValidateAudience = true,

    ValidAudience = audience,//订阅人

    ValidateLifetime = true,

    ClockSkew = TimeSpan.Zero,

    RequireExpirationTime = true,


    };

    var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

    //如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名

    var permissionRequirement = new PermissionRequirement(

    deniedUrl,

    ClaimTypes.Role,

    issuer,

    audience,

    signingCredentials,

    expiration: TimeSpan.FromHours(10)

    );

    //注入授权Handler

    services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

    services.AddSingleton(permissionRequirement);

    return services.AddAuthorization(options =>

    {

    options.AddPolicy(policyName,

    policy => policy.Requirements.Add(permissionRequirement));


    })

    .AddAuthentication(options =>

    {

    options.DefaultScheme = defaultScheme;

    })

    .AddJwtBearer(defaultScheme, o =>

    {

    //不使用https

    o.RequireHttpsMetadata = isHttps;

    o.TokenValidationParameters = tokenValidationParameters;

    });

    }

    /// <summary>

    /// 注入Token生成器参数,在token生成项目的Startup的ConfigureServices中使用

    /// </summary>

    /// <param name="services">IServiceCollection</param>

    /// <param name="issuer">发行人</param>

    /// <param name="audience">订阅人</param>

    /// <param name="secret">密钥</param>

    /// <param name="deniedUrl">拒绝路由</param>

    /// <returns></returns>

    public static IServiceCollection AddJTokenBuild(this IServiceCollection services, string issuer, string audience, string secret, string deniedUrl)

    {

    var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)), SecurityAlgorithms.HmacSha256);

    //如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名

    var permissionRequirement = new PermissionRequirement(

    deniedUrl,

    ClaimTypes.Role,

    issuer,

    audience,

    signingCredentials,

    expiration: TimeSpan.FromHours(10)

    );

    return services.AddSingleton(permissionRequirement);


    }


    }

    }

    接下来看AuthenticationAPI项目:

    appsettings.json

    {

    "Logging": {

    "IncludeScopes": false,

    "Debug": {

    "LogLevel": {

    "Default": "Information"

    }

    },

    "Console": {

    "LogLevel": {

    "Default": "Information"

    }

    }

    },

    "Audience": {

    "Secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",

    "Issuer": "gsw",

    "Audience": "everone"

    }

    }

    Startup.cs


    using Microsoft.AspNetCore.Builder;

    using Microsoft.AspNetCore.Hosting;

    using Microsoft.Extensions.Configuration;

    using Microsoft.Extensions.DependencyInjection;

    using Ocelot.JWTAuthorizePolicy;


    namespace AuthenticationAPI

    {

    public class Startup

    {

    public Startup(IConfiguration configuration)

    {

    Configuration = configuration;

    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)

    {

    var audienceConfig = Configuration.GetSection("Audience");

    //注入OcelotJwtBearer

    services.AddJTokenBuild(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "/api/denied");

    services.AddMvc();

    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    {

    if (env.IsDevelopment())

    {

    app.UseDeveloperExceptionPage();

    }

    app.UseMvc();

    }

    }

    }

    PermissionController.cs


    using System;

    using Microsoft.AspNetCore.Mvc;

    using Microsoft.AspNetCore.Authorization;

    using System.Security.Claims;

    using Microsoft.AspNetCore.Authentication.JwtBearer;

    using Ocelot.JWTAuthorizePolicy;


    namespace AuthenticationAPI

    public class PermissionController : Controller

    {

    /// <summary>

    /// 自定义策略参数

    /// </summary>

    PermissionRequirement _requirement;

    public PermissionController(PermissionRequirement requirement)

    {

    _requirement = requirement;

    }

    [AllowAnonymous]

    [HttpPost("/authapi/login")]

    public IActionResult Login(string username, string password)

    {

    var isValidated = (username == "gsw" && password == "111111")|| (username == "ggg" && password == "222222");

    var role=username=="gsw"?"admin" :"system";

    if (!isValidated)

    {

    return new JsonResult(new

    {

    Status = false,

    Message = "认证失败"

    });

    }

    else

    //如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色

    var claims = new Claim[] { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role), new Claim(ClaimTypes.Expiration ,DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())};

    //用户标识

    var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);

    identity.AddClaims(claims);


    var token = JwtToken.BuildJwtToken(claims, _requirement);

    return new JsonResult(token);

    }

    }

    }

    DemoAAPI项目,DemoBAPI项目类似

    appsettings.json与网关,AuthenticationAPI相同
    Startup.cs

    using System.Collections.Generic;

    using Microsoft.AspNetCore.Builder;

    using Microsoft.AspNetCore.Hosting;

    using Microsoft.Extensions.Configuration;

    using Microsoft.Extensions.DependencyInjection;

    using Microsoft.Extensions.Logging;

    using Ocelot.JWTAuthorizePolicy;


    namespace DemoAAPI

    {

    public class Startup

    {

    public Startup(IConfiguration configuration)

    {

    Configuration = configuration;

    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)

    {

    //读取配置文件

    var audienceConfig = Configuration.GetSection("Audience");

    services.AddOcelotPolicyJwtBearer(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "GSWBearer", "Permission", "/demoaapi/denied");


    //这个集合模拟用户权限表,可从数据库中查询出来

    var permission = new List<Permission> {

    new Permission { Url="/demoaapi/values", Name="system"},

    new Permission { Url="/", Name="system"} 

    };

    services.AddSingleton(permission);

    services.AddMvc();

    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    {

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));

    if (env.IsDevelopment())

    {

    app.UseDeveloperExceptionPage();

    }

    app.UseMvc();

    }

    }

    }

    ValuesController.cs


    using System.Collections.Generic;

    using Microsoft.AspNetCore.Authorization;

    using Microsoft.AspNetCore.Mvc;


    namespace DemoAAPI.Controllers

    {

    [Authorize("Permission")]

    [Route("demoaapi/[controller]")]

    public class ValuesController : Controller

    [HttpGet]

    public IEnumerable<string> Get()

    {

    return new string[] { "DemoA服务", "请求" };

    }

    [AllowAnonymous]

    [HttpGet("/demoaapi/denied")]

    public IActionResult Denied()

    {

    return new JsonResult(new

    {

    Status = false,

    Message = "demoaapi你无权限访问"

    });

    }

    }

    }

    OcelotGateway项目

    configuration.json,注意每个连接的AuthenticationOptions. AuthenticationProviderKey,要设置成

    {

    "ReRoutes": [

    {

    "DownstreamPathTemplate": "/demoaapi/values",

    "DownstreamScheme": "http",

    "DownstreamPort": 5001,

    "DownstreamHost": "localhost",

    "UpstreamPathTemplate": "/demoaapi/values",

    "UpstreamHttpMethod": [ "Get" ],

    "QoSOptions": {

    "ExceptionsAllowedBeforeBreaking": 3,

    "DurationOfBreak": 10,

    "TimeoutValue": 5000

    },

    "HttpHandlerOptions": {

    "AllowAutoRedirect": false,

    "UseCookieContainer": false

    },

    "AuthenticationOptions": {

    "AuthenticationProviderKey": "GSWBearer",

    "AllowedScopes": []

    }

    },

    {

    "DownstreamPathTemplate": "/demoaapi/denied",

    "DownstreamScheme": "http",

    "DownstreamPort": 5001,

    "DownstreamHost": "localhost",

    "UpstreamPathTemplate": "/demoaapi/denied",

    "UpstreamHttpMethod": [ "Get" ],

    "QoSOptions": {

    "ExceptionsAllowedBeforeBreaking": 3,

    "DurationOfBreak": 10,

    "TimeoutValue": 5000

    },

    "AuthenticationOptions": {

    }

    },

    {

    "DownstreamPathTemplate": "/demobapi/values",

    "DownstreamScheme": "http",

    "DownstreamPort": 5002,

    "DownstreamHost": "localhost",

    "UpstreamPathTemplate": "/demobapi/values",

    "UpstreamHttpMethod": [ "Get" ],

    "QoSOptions": {

    "ExceptionsAllowedBeforeBreaking": 3,

    "DurationOfBreak": 10,

    "TimeoutValue": 5000

    },

    "HttpHandlerOptions": {

    "AllowAutoRedirect": false,

    "UseCookieContainer": false

    },

    "AuthenticationOptions": {

    "AuthenticationProviderKey": "GSWBearer",

    "AllowedScopes": []

    }

    },

    {

    "DownstreamPathTemplate": "/demobapi/denied",

    "DownstreamScheme": "http",

    "DownstreamPort": 5002,

    "DownstreamHost": "localhost",

    "UpstreamPathTemplate": "/demobapi/denied",

    "UpstreamHttpMethod": [ "Get" ],

    "QoSOptions": {

    "ExceptionsAllowedBeforeBreaking": 3,

    "DurationOfBreak": 10,

    "TimeoutValue": 5000

    },

    "AuthenticationOptions": {

    }

    },

    {

    "DownstreamPathTemplate": "/authapi/login",

    "DownstreamScheme": "http",

    "DownstreamPort": 5003,

    "DownstreamHost": "localhost",

    "UpstreamPathTemplate": "/authapi/login",

    "UpstreamHttpMethod": [ "Get", "Post" ],

    "QoSOptions": {

    "ExceptionsAllowedBeforeBreaking": 3,

    "DurationOfBreak": 10,

    "TimeoutValue": 5000

    },

    "AuthenticationOptions": {

    }

    }

    ]

    }

    Startup.cs


    using Microsoft.AspNetCore.Builder;

    using Microsoft.AspNetCore.Hosting;

    using Microsoft.Extensions.Configuration;

    using Microsoft.Extensions.DependencyInjection;

    using Ocelot.DependencyInjection;

    using Ocelot.Middleware;

    using Ocelot.JWTAuthorizePolicy;

    namespace OcelotGateway

    {

    public class Startup

    {

    public Startup(IConfiguration configuration)

    {

    Configuration = configuration;

    }

    public IConfiguration Configuration { get; } 

    public void ConfigureServices(IServiceCollection services)

    {

    var audienceConfig = Configuration.GetSection("Audience");

    //注入OcelotJwtBearer

    services.AddOcelotJwtBearer(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "GSWBearer");

    //注入配置文件,AddOcelot要求参数是IConfigurationRoot类型,所以要作个转换

    services.AddOcelot(Configuration as ConfigurationRoot);

    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    {

    app.UseOcelot().Wait();

    }

    }

    }

    接下来是测试项目,创建一个控制项目TestClient

    Nuget中添加RestSharp包
    Program.cs

    using RestSharp;

    using System;

    using System.Diagnostics;


    namespace TestClient

    {

    class Program

    {

    /// <summary>

    /// 访问Url

    /// </summary>

    static string _url = "http://127.0.0.1:5000";

    static void Main(string[] args)

    {


    Console.Title = "TestClient";

    dynamic token = null;

    while (true)

    {

    Console.WriteLine("1、登录【admin】 2、登录【system】 3、登录【错误用户名密码】 4、查询HisUser数据 5、查询LisUser数据 ");

    var mark = Console.ReadLine();

    var stopwatch = new Stopwatch();

    stopwatch.Start();

    switch (mark)

    {

    case "1":

    token = AdminLogin();

    break;

    case "2":

    token = SystemLogin();

    break;

    case "3":

    token = NullLogin();

    break;

    case "4":

    DemoAAPI(token);

    break;

    case "5":

    DemoBAPI(token);

    break;

    }

    stopwatch.Stop();

    TimeSpan timespan = stopwatch.Elapsed;

    Console.WriteLine($"间隔时间:{timespan.TotalSeconds}");

    tokenString = "Bearer " + Convert.ToString(token?.access_token);

    }

    }

    static string tokenString = "";

    static dynamic NullLogin()

    {

    var loginClient = new RestClient(_url);

    var loginRequest = new RestRequest("/authapi/login", Method.POST);

    loginRequest.AddParameter("username", "gswaa");

    loginRequest.AddParameter("password", "111111");

    //或用用户名密码查询对应角色

    loginRequest.AddParameter("role", "system");

    IRestResponse loginResponse = loginClient.Execute(loginRequest);

    var loginContent = loginResponse.Content;

    Console.WriteLine(loginContent);

    return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

    }


    static dynamic SystemLogin()

    {

    var loginClient = new RestClient(_url);

    var loginRequest = new RestRequest("/authapi/login", Method.POST);

    loginRequest.AddParameter("username", "ggg");

    loginRequest.AddParameter("password", "222222");

    IRestResponse loginResponse = loginClient.Execute(loginRequest);

    var loginContent = loginResponse.Content;

    Console.WriteLine(loginContent);

    return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

    }

    static dynamic AdminLogin()

    {

    var loginClient = new RestClient(_url);

    var loginRequest = new RestRequest("/authapi/login", Method.POST);

    loginRequest.AddParameter("username", "gsw");

    loginRequest.AddParameter("password", "111111");

    IRestResponse loginResponse = loginClient.Execute(loginRequest);

    var loginContent = loginResponse.Content;

    Console.WriteLine(loginContent);

    return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

    }

    static void DemoAAPI(dynamic token)

    {

    var client = new RestClient(_url);

    //这里要在获取的令牌字符串前加Bearer

    string tk = "Bearer " + Convert.ToString(token?.access_token);

    client.AddDefaultHeader("Authorization", tk);

    var request = new RestRequest("/demoaapi/values", Method.GET);

    IRestResponse response = client.Execute(request);

    var content = response.Content;

    Console.WriteLine($"状态码:{(int)response.StatusCode} 状态信息:{response.StatusCode} 返回结果:{content}");

    }

    static void DemoBAPI(dynamic token)

    {

    var client = new RestClient(_url);

    //这里要在获取的令牌字符串前加Bearer

    string tk = "Bearer " + Convert.ToString(token?.access_token);

    client.AddDefaultHeader("Authorization", tk);

    var request = new RestRequest("/demobapi/values", Method.GET);

    IRestResponse response = client.Execute(request);

    var content = response.Content; Console.WriteLine($"状态码:{(int)response.StatusCode} 状态信息:{response.StatusCode} 返回结果:{content}");

    }

    }

    }


    相关文章:

    原文:http://www.cnblogs.com/axzxs2001/p/8005084.html


    .NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

    展开全文
  • 2 Nginx集群之基于Redis的WebApi身份验证... 1 3 Redis数据库... 2 4 Visualbox虚拟机ubuntu下的redis部署... 3 5 编写.NET WebApi的OnAuthorization身份验证... 6 6 编写.NET WebApi的A
  • c#之webapi

    万次阅读 2015-08-04 15:28:12
    c#之webapi 不管是因为什么原因,结果是在新出的MVC中,增加了WebAPI,用于提供REST风格的WebService,个人比较喜欢REST风格的WebService,感觉比SOAP要轻量级一些,而且对客户端的要求也更少,更符合网络数据传输...
  • using Magic.Tool;...using System.Web; using System.Web.Mvc; using System.Web.Routing; //MVC中全局错误拦截 namespace Magic.Mvc { public class MvcApplication : System.Web.HttpApplication ...
  • .net core webapi (1) 搭建

    千次阅读 2019-03-15 11:43:34
    以.NET Core为框架,搭建出一个功能完善的WebApi框架。实现后台管理系统、前台系统和App系统的统一管理。 该框架欲集成Swagger作为接口显示文档,集成SqlSugar作为数据库操作ORM,集成LayUI作为后台管理系统前端框架...
  • JWT 身份验证引言引用依赖包添加身份认证相关服务到容器中swagger 中配置JWT开启中间件生成Token获取claims中的参数信息接口中添加[Authorize()]jwt 自定义策略 引言 JWT定义与优缺点 引用依赖包 Microsoft....
  • ASP.NET 5.0 的主要目标之一是统一 MVC 和 Web API 框架应用。
  • 用户身份验证/权限验证, 根据接口指定的安全级别,进行相应的安全验证。 文档/代码生成, 符合网关定义规范的接口会由网关统一产生文档和不同语言的客户端sdk 其他想不起来了, 等我想起来再补充。 接口文档示例 ...
  • WebAPI接口开发实践

    千次阅读 2020-02-02 16:29:53
    背景 在团队两年多陆续负责了几个项目的开发上线已经代码的...WebAPI开发流程 第一步首先设计接口文档,公司内部有一套自研的多人协作文档系统,可以很好的做到这一步,并能很好的做好版本控制。如果公司内部没...
  • asp.net WebAPI OWIN OAuth2.0授权自定义返回结果及错误或异常问题处理核心代码,详情: https://www.cnblogs.com/wgx0428/p/12315546.html
  • Web API应用架构设计分析(1) Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端(包括浏览器,手机和平板电脑等移动设备)的框架,ASP.NET Web API 是一种用于在 .NET Framework 上构建 ...
  • Web API系列(二)接口安全和参数校验

    千次阅读 2018-08-17 16:57:34
    以前简单介绍过web api 的设计,但是还是有很多朋友问我,如何合理的设计和实现web api。比如,接口安全,异常处理,统一数据返回等问题。所以有必要系统的总结总结 web api 的设计和实现。由于前面已经介绍过web ...
  • 开发环境:ASP.NET Core Web API 目标框架:.NET Core 2.2 权限认证:JWT Bearer 提供者:成长的小猪 Jason Song 应用场景:当前我们给微信小程序提供服务接口,接口中使用了权限认证这一块,当我使用 JWT Bearer ...
  • 基于ThinkPHP开发RESTful Web API

    万次阅读 2016-12-06 16:57:55
    REST是一种风格,而不是标准。...REST并没有创造新的技术,组件或服务,隐藏在RESTful Web API背后的理念是使用Web的现有特征和能力。RESTful Web API定义了如何更好地使用现有Web标准中的一些准则和约束。
  • Web API应用支持HTTPS的经验总结

    千次阅读 2015-11-03 15:03:49
    在我前面介绍的WebAPI文章里面,介绍了WebAPI的架构设计方面的内容,其中提出了现在流行的WebAPI优先的路线,这种也是我们开发多应用(APP、微信、微网站、商城、以及Winform等方面的整合)的时候值得考虑的线路之一...
  • webapi token、参数签名是如何生成的

    万次阅读 2017-06-06 00:53:25
    API接口保障安全性原则:1.有调用者身份2.请求的唯一性3.请求的参数不能被篡改4.请求的有效时间 在刚接触接口开发时,可能脑子里压根就没有这个接口调用安全性的原则,但常识性的经验告诉我们,每一个请求都应该...
  • Ocelot统一权限验证 Ocelot监控 给Ocelot做一个Docker 镜像 Ocelot + Consul实践 .NET Core开源API网关 – Ocelot中文文档 .NET微服务体系结构中为什么使用Ocelot实现API网关 .NET Core微服务之基于Ocelot实现API...
  • WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理。引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想,通过Filter能统一地对一些通用逻辑进行...
  • 在《Web API应用架构设计分析(1)》和《Web API应用架构设计分析(2)》中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己的Web API平台,方便各种终端系统的接入,很多...
  • WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理。引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想,通过Filter能统一地对一些通用逻辑进行...
  • 本课程是基于vue-element-admin实现的后台权限验证系统,解决在前后端分离场景下如何实现前端与后端的动态权限,同时还会讲解基于laravel7.x的restful api接口的开发以及如何在脚手架中进行封装调用 对于前后端将要...
  • WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理。引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想,通过Filter能统一地对一些通用逻辑进行...
  • 防止未授权用户访问,使用用户token验证 防止未授权应用访问或者爬虫,使用appid,appsecret来保证请求授权访问 防止dos攻击浪费资源,使用时间戳timestamp 防止信息泄露,使用https安全访问 防止重放 ...
  • NETCORE Ocelot网关下的API统一JWT鉴权

    千次阅读 2019-12-27 20:23:23
    本文章主要整理并分享 netcore2.2 版本 Ocelot网关下,各个api使用JWT验证实现统一鉴权验证(代码如有雷同请多包涵) 项目所用到的NuGet包版本: net core (2.2.0) , Ocelot(13.5.2) 园内很多blog都有介绍JWT...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,616
精华内容 10,246
关键字:

webapi统一权限验证