cover_image

【Blog.Core开源】开发插件,给Swagger加权

老张的哲学 MVP BCVP代码创新社
2021年12月04日 07:40

图片

业精于勤荒于嬉,_ _ _ _ _ _ _



大家周末好,前两天有个小伙伴在社区里咨询了一个小问题,如何给Swagger页面增加权限,虽然每个接口都已经有了权限,但是还是不想要所有人都能看到接口列表。如果大家没有考虑过这个问题,可以先暂停下,不往下看,喝杯水,思考下如果是自己的话会怎么设计这个需求:

1、过程不要很复杂,但是又可以自由的扩展(下文会说到);

2、重要的一点就是不能对当前项目过多的影响和侵入

我简单的设计了一个方案,可能不是最优解,如果小伙伴有不同的意见,或者更好的建议,欢迎留言哟。废话不多说,马上上代码。


PS:Blog.Core线上已经集成了这个方案,可以自行访问下试试。

地址:http://apk.neters.club/



01
PART
自定义Swagger权限拦截中间件



很简单,既然要对Swagger的.html页面进行限制,常规的思路都是增加一个拦截器之类的,那自然而然的就想到了ASP.NetCore的中间件,目前Blog.Core已经集成了16个中间件,涵盖了平时开发需要用到的服务列表、本地Mock用户、异常、限流、审计、权限、MiniProfiler、种子数据、任务调度、Swagger等等,感兴趣的可以一一拆分出来看看学习。


直接上代码:

namespace Blog.Core.Middlewares{    public class SwaggerAuthMildd    {
private readonly RequestDelegate next;
public SwaggerAuthMildd(RequestDelegate next) { this.next = next; }
public async Task InvokeAsync(HttpContext context) { // 也可以根据是否是本地做判断 IsLocalRequest if (context.Request.Path.Value.ToLower().Contains("index.html")) { // 判断权限是否正确 if (IsAuthorized(context)) { await next.Invoke(context); return; }
// 无权限,跳转swagger登录页 context.Response.Redirect("/swg-login.html"); } else { await next.Invoke(context); } }
public bool IsAuthorized(HttpContext context) { // 使用session模式 // 可以使用其他的 return context.Session.GetString("swagger-code") == "success"; }
/// <summary> /// 判断是不是本地访问 /// 本地不用swagger拦截 /// </summary> /// <param name="context"></param> /// <returns></returns> public bool IsLocalRequest(HttpContext context) { if (context.Connection.RemoteIpAddress == null && context.Connection.LocalIpAddress == null) { return true; } if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress)) { return true; } if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress)) { return true; } return false; } }    // 定义扩展 public static class SwaggerAuthorizeExtensions { public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder) { return builder.UseMiddleware<SwaggerAuthMildd>(); } }}


代码比较简单,主要是拦截了下index.html,因为我是自定义的Swagger首页,如果你有不同的设计,可以酌情修改代码。

此外权限判断的依据,我是用的Session作为当前登录依据,如果存在Session,证明通过,否则跳转到Swagger的登录页,如果浏览器关闭或者换了其他地方Session失效的话,就需要重新登陆,这当然无伤大雅,只要保证浏览器不关闭,其实一直调试是没问题的。


然后就在Startup的中间件管理里,增加上刚刚定义好的中间件扩展方法就行了,而且用到了Session,就需要配置下session的服务注入和中间件:

// 注册服务services.AddSession();
// 使用中间件,放到Swagger中间件之前app.UseSession();app.UseSwaggerAuthorized();




02
PART
Swagger登录页设计



上边咱们配置好了中间件,现在就需要配置下无权限的时候的跳转页面了,直接在wwwroot文件夹里新建一个swg-login.html:

<!DOCTYPE html><html><head>    <meta charset="utf-8" />    <title>默认首页</title>    <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
</head><body> <div id="requestMsg"></div> <div style="text-align: center;"> <p>用户名:admin,密码:admin</p> <input id="name" placeholder="name" type="text" /> <br /> <input id="pwd" placeholder="pwd" type="password" /> <br /> <input type="submit" onclick="submit()" value="submit" /> </div> <script> function submit() { let postdata = { "name": $("#name").val(), "pwd": $("#pwd").val(), }; if (!(postdata.name && postdata.pwd)) { alert('参数不正确'); return } $.ajax({ url: "/api/Login/swgLogin", type: "POST", contentType: "application/json; charset=utf-8", data: JSON.stringify(postdata), dataType: 'json', success: function (data) { if (data?.result) { window.location.href = "/index.html"; } else { alert('参数不正确'); } } }); }</script></body></html>


代码很简单,就是做一个Ajax的Post请求,成功后跳转到Swagger的index页面即可。



03
PART
Swagger的登录接口



这一块就更简单了,直接接收用户名和密码就行,然后存到Session里,其实这一块的扩展性很强,无论是简单的登录,还是连接数据的登录都是可以的:

 /// <summary> /// swagger登录 /// </summary> /// <param name="loginRequest"></param> /// <returns></returns> [HttpPost] [Route("swgLogin")] public dynamic SwgLogin([FromBody] SwaggerLoginRequest loginRequest) {     // 这里可以查询数据库等各种校验     if (loginRequest?.name == "admin" && loginRequest?.pwd == "admin")     {         HttpContext.Session.SetString("swagger-code", "success");         return new { result = true };     }
return new { result = false }; }


到这里基本都已经完成了,很简单的过程,来个效果动图看看吧

图片



04
PART
其他说明


其实本文只是众多思路当中的一个,你可以发散思维,比如直接在我们的Swagger自定义的首页里做操作,毕竟是自定义的index.html嘛,可以加个登录。


也可以使用我这种单独登录页面的方案,再丰富些,对接ids4认证中心等等,都是不错的想法和思路。


好啦,今天就到这里了,欢迎更多的小伙伴来分享更好更棒的思路吧。

Github开源项目 · 目录
上一篇升级Jenkins镜像,支持.NET6.0下一篇在ASP.Net Core和JAVA中,使用Azure配置密钥——Key Vault
继续滑动看下一个
BCVP代码创新社
向上滑动看下一个