使用另一种身份验证方法进行外部 api 调用

2024-02-21

我有一个带有 MVC 的 Web API 应用程序。当用户使用网站时,身份验证和授权当前由我使用的全局表单身份验证自动处理,在 Web.config 中配置如下:

<authentication mode="Forms">
  <forms loginUrl="~/Login" slidingExpiration="true" timeout="1800" defaultUrl="/"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>

这可确保只有登录的用户才能访问该网站并调用 API。

但我还有一个外部 Windows 客户端,我想为其使用另一种身份验证方法。在没有表单身份验证的测试中,我设置了一个自定义 AuthorizeAttribute,可以在控制器中使用它,如下所示:

[ApiAuth]
public IEnumerable<string> Get() {
    // Return the resource
}

AuthorizeAttribute 看起来像这样:

public class ApiAuthAttribute : AuthorizeAttribute {
    public override void OnAuthorization(HttpActionContext context) {
        // Authenticate the request with a HMAC-based approach
    }
}

这在孤立的情况下工作得很好,但我不知道如何允许这两种身份验证方法。如果表单身份验证不起作用(或相反,无论起作用),我希望将 ApiAuth 作为后备,但如果我应用 [ApiAuth] 属性,则仅使用该属性,普通用户无法访问 api。

那么,如何使用多种身份验证方法,要么使用其中一种方法作为另一种方法失败时的后备方法,要么配置服务器,以便 Windows 客户端可以通过 MVC 应用程序以外的其他方式调用 API,同时仍然保持相同API 调用对两种类型的客户端都可用吗?

谢谢。


Edit:我可能采取的一种方法是让 Windows 客户端使用表单 auth 进行身份验证(类似于this https://stackoverflow.com/a/1879216/4688606),但它看起来很像黑客,我宁愿使用其他方法。


FormAuthentication可以通过多种方式实现。在过去,我们使用表单验证票 https://stackoverflow.com/a/38975468/296861.

现在,您可以通过 Owin Middleware 使用基于声明的身份验证,它基本上是 ASP.Net Identity 的精简版本。

在您对内部用户进行身份验证后ApiAuth属性,您创建主体对象。

网页配置

你不应该使用<authorization>ASP.Net MVC 中的标记。相反,你想使用Filter.

<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>

ApiAuth属性

public class ApiAuthAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext context)
    {
        // Authenticate the request with a HMAC-based approach

        // Create FormAuthentication after custom authentication is successful
        if (!HttpContext.Current.User.Identity.IsAuthenticated)
        {
            User user = new User {Id = "1234", UserName = "johndoe", 
                 FirstName = "John", LastName = "Doe"};

            // This should be injected using IoC container. 
            var service = new OwinAuthenticationService(
                 new HttpContextWrapper(HttpContext.Current));
            service.SignIn(user);
        }
    }
}

验证

public class User
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public interface IAuthenticationService
{
    void SignIn(User user);
    void SignOut();
}

public class OwinAuthenticationService : IAuthenticationService
{
    private readonly HttpContextBase _context;
    private const string AuthenticationType = "ApplicationCookie";

    public OwinAuthenticationService(HttpContextBase context)
    {
        _context = context;
    }

    public void SignIn(User user)
    {
        IList<Claim> claims = new List<Claim>
        {
            new Claim(ClaimTypes.Sid, user.Id),
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(ClaimTypes.GivenName, user.FirstName),
            new Claim(ClaimTypes.Surname, user.LastName),
        };

        /*foreach (Role role in user.Roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role.Name));
        }*/

        ClaimsIdentity identity = new ClaimsIdentity(claims, AuthenticationType);

        IOwinContext context = _context.Request.GetOwinContext();
        IAuthenticationManager authenticationManager = context.Authentication;

        authenticationManager.SignIn(identity);
    }

    public void SignOut()
    {
        IOwinContext context = _context.Request.GetOwinContext();
        IAuthenticationManager authenticationManager = context.Authentication;

        authenticationManager.SignOut(AuthenticationType);
    }
}

启动.cs

[assembly: OwinStartup(typeof(YOUR_APPLICATION.Startup))]
namespace YOUR_APPLICATION
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "ApplicationCookie",
                LoginPath = new PathString("/Account/Login")
            });
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用另一种身份验证方法进行外部 api 调用 的相关文章

随机推荐

  • 没有名为 pyVim 的模块

    我正在使用 python 3 7 5 运行 Catalina MacOS 我正在尝试运行 ansible 脚本来安装虚拟机 这需要 python gt 2 6 和 PyVmomi 我已经通过 pip 安装了 PyVomi 和 pyVim 两
  • 如何在同一视图控制器上呈现表格视图和二维码扫描仪?

    我想要实现的目标是让屏幕的下半部分成为活动的二维码扫描仪 而屏幕的另一半成为表格视图 每当我扫描二维码时 它都会检查表格视图是否匹配并突出显示它 我需要用什么来实现这一点 我使用以下 cocoapod 作为二维码 https cocoapo
  • 适用于 Android 的心率传感器 API

    谷歌已经发布了有关可穿戴设备的API 由于许多智能手表制造商都声称他们有心率传感器 我想知道 android 是否为其发布了 api 我检查了网络并没有找到任何东西 有谁对可穿戴设备开发感兴趣并且知道这件事吗 Thanks 截至目前 这些
  • 如何在角度4中使用renderer2动态追加子项

    我是 Angular 4 的新手 需要使用 html 列表在 child 下添加 child Component selector my app template div ul root ul div export class App im
  • 动态委托给最小的 api

    各位程序员大家好 基本上 我想将动态构建的委托传递给最小的 api MapGet 或 MapPost 方法 这是构造委托的方法 private static Delegate GetDelegate Type type MethodInfo
  • Xamarin Forms WebView 检查网站地址何时更改

    我有以下代码在我的 Xamarin Forms 跨平台应用程序中设置 WebView ReportsListWebView new WebView VerticalOptions LayoutOptions FillAndExpand Ho
  • geocoder.getFromLocationName 仅返回 null

    这两天我快要疯了IllegalArgumentException当尝试从地址中获取坐标 甚至反向获取经度和纬度地址时 我在 Android 代码中收到错误 这是代码 但我看不到错误 它是一个标准代码片段 很容易在 Google 搜索中找到
  • Mercurial:远程:中止:这里没有 Mercurial 存储库(未找到 .hg)!

    all 我已经寻找这个问题很长时间并尝试了不同的方法 我想仅通过 SSH 在服务器上维护我的代码 但是当我运行这个时 sudo hg clone v ssh carl hostname home carl Java Projects pet
  • 20hz-20000hz 巴特沃斯滤波爆炸

    我想过滤掉 20 Hz 20000 Hz 之外的所有内容 我正在使用巴特沃斯滤波器 from scipy io import wavfile from scipy import signal import numpy sr x wavfil
  • Javascript 字符串大小限制:对我来说是 256 MB - 所有浏览器都一样吗?

    我很好奇我能在 Javascript 中获得的最大字符串长度是多少 今天我在 Windows 7 中运行的 Firefox 43 0 1 上亲自测试了它 我能够构造一个具有长度的字符串2 28 1 但是当我尝试创建一个多一个字符的字符串时
  • C# ImageFormat 转字符串

    我怎样才能获得人类可读的字符串 即图像格式本身 来自系统 绘图 图像格式目的 我的意思是如果我有ImageFormat Png是否可以将其转换为 png 字符串 EDIT 我在这里看到一些误解 这是我的代码 Image objImage I
  • 如何检测是否在osgi容器中运行

    我有一个 OSGi 包 也可以在纯 Java 进程中运行 我需要能够判断捆绑包是否已加载到 OSGi 系统中 我怎样才能做到这一点 如果没有 OSGi 标准方法来执行此操作 我将采用 Eclipse Equinox 特定的方法 将 Bund
  • Safari 11 X-XSRF-TOKEN 刷新后未更新

    最近 Mac OSX 上的 Safari 11 发布 此更新导致我们的 Web 应用程序与请求标题上的 XSRF 结合出现问题 我将尝试以逻辑方式描述问题 好的情况应该是这样的 当用户想要登录时 他会收到服务器的响应 其中包含包含 XSRF
  • 如何使用 React 和表单来获取选中的复选框值的数组?

    我正在尝试为我的投资组合网站构建一个过滤器 复选框可让您选择一种技术 react redux jquery 等 来显示包含该技术的作品 因此 每次用户单击某个框时 我都想将值 JavaScript Redux React 等 添加到一个数组
  • 绿色线程是否等于“真实”线程

    我从以下位置获取了示例代码理解 eventlet wsgi server https stackoverflow com questions 8509209 unterstanding eventlet wsgi server from e
  • 使用 CSS 更改悬停时的文本颜色

    我已经搜索过 但找不到与我遇到的这个问题相关的任何内容 我多年来一直试图解决这个问题 但似乎无法做到 我有一个 div 里面有文本和图像 我希望当我将鼠标悬停在 div 内的任何位置时 div 内的所有文本和背景都会改变颜色 我已经做到了底
  • 电视指南列表 API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 无法从 Apple 开发者中心删除 App ID

    我已经看到 Apple 更改了 iOS 开发中心的证书 标识符和配置文件页面 并在堆栈上阅读此问题 答案 从开发者连接中删除应用程序 ID https stackoverflow com questions 996477 removing
  • 如何使用 ajax get 或 post 在 mvc 中使用参数将数据从视图传递到控制器

    我正在尝试使用 ajax 将数据从视图传递到控制器操作方法 如下所示 我有一个用户的 Membership 实例 我使用 viewbag 从另一个控制器传递到下面的这个视图 有点像这样 ViewBag MyUser MyUser 现在我想使
  • 使用另一种身份验证方法进行外部 api 调用

    我有一个带有 MVC 的 Web API 应用程序 当用户使用网站时 身份验证和授权当前由我使用的全局表单身份验证自动处理 在 Web config 中配置如下