c# - ASP.NET Identity 2.0 针对我们自己的承载服务器进行身份验证

标签 c# asp.net-mvc authentication owin asp.net-identity-2

全部,

我有一个安全服务器,其唯一目的是从单个端点提供不记名 token :http://example.com/token

示例请求:

POST http://example.com/token HTTP/1.1
User-Agent: Fiddler
Content-Type: x-www-form-urlencoded
Host: example.com
Content-Length: 73

grant_type=password&username=example@example.com&password=examplePassword

示例响应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Expires: -1
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 16 Aug 2016 12:04:39 GMT
{
  "access_token": "xxxx",
  "token_type": "bearer",
  "expires_in": 17999,
  "refresh_token": "xxxx",
  ".issued": "Tue, 16 Aug 2016 12:04:38 GMT",
  ".expires": "Tue, 16 Aug 2016 17:04:38 GMT"
}

我们有一个使用此端点进行身份验证的角度应用程序,并且做得很好。

我们正在尝试创建一个使用同一服务器进行身份验证的 MVC 应用程序但没有取得太大成功,如果可能的话,我们希望代码位于 Identity 2.0 之上。

在我们的 AccountController(示例项目)中,我们有我们的 Login(LoginModel model) 方法来处理登录,看起来像这样(与示例项目模板相同):

var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);

我们有自己的 IUserStore、UserManager、SignInManager 实现。

我考虑过覆盖

public Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout) on `SignInManager<,>` and make a web call across to the security server.

PasswordSignInAsync 的默认实现调用 UserManager.FindByNameAsync 但是这意味着我必须在我的安全服务器上公开一个查找方法以确认用户名确实存在听起来不太好。

我一定遗漏了什么,我知道不会这么复杂,我们的 MVC 应用程序需要使用 cookie 身份验证,但也需要为后续调用我们的其他资源服务器维护 bear token 。

(我很感激我可能在这里混淆了技术,因此出现了这个问题)。

这也在 OWIN 上运行。

最佳答案

在这种情况下,我认为您不应该在 MVC 应用程序中使用 Identity 2.0。你应该创建一个 AuthenticationClient 来调用你的身份验证服务器,你也可以使用这个库来构建这样一个客户端 https://www.nuget.org/packages/Thinktecture.IdentityModel.Client/

public class AuthenticationClient {
    public ClaimsIdentity GetClaimsIdentity(string username, string password) {
         //Call your authentication server to get your token and also claims associated with your identity.
         //You can look at an example code how to do it: https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/ConsoleResourceOwnerClient/Program.cs
         //and create a ClaimsIdentity object out of those information

         var identity = GetIdentity();

         //The key point here is to add AccessToken and RefreshToken as custom claims to your identity so you retrieve these tokens back on subsequent requests.
        identity.AddClaim(new Claim("access_token", accessToken));
        identity.AddClaim(new Claim("refresh_token", refreshToken));
    }
}

这将满足您的要求:

Use cookie authentication but also maintain the bear token for subsequent calls to our other resource server.

AccountController 上的Login 方法应该是这样的:

public ActionResult Login(LoginModel model)
{
     var identity = authenticationClient.GetClaimsIdentity(model.UserName, model.Password);

     if (identity == null) {
         return new HttpUnauthorizedResult();
     }
     //Sign in the user
     var ctx = Request.GetOwinContext();
     var authenticationManager = ctx.Authentication;
     authenticationManager.SignIn(identity);

     return new HttpStatusCodeResult(HttpStatusCode.OK);
}

我假设你已经注册了这个中间件来使用 Cookie 认证:

public void ConfigureAuth(IAppBuilder app)
{
   app.UseCookieAuthentication(new CookieAuthenticationOptions
   {
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
      LoginPath = new PathString("/Account/Login")
   });
}

现在对于所有后续请求,您可以取回访问 token 以从您的 ClaimsIdentity 调用您的资源服务器:

User.Identity.Claims.FirstOrDefault(x => x.Type == "access_token");

关于c# - ASP.NET Identity 2.0 针对我们自己的承载服务器进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38974765/

相关文章:

authentication - 在 Clojure 中执行用户身份验证和授权的首选方法是什么?

c# - 如何从另一个类访问 form1 变量?

javascript - 从 Mvc 模型渲染 div

c# - ASP.NET MVC ModelBinder 自定义字段映射

java - Android 上如何识别用户?

typescript - 在 Next.js 中的高阶身份验证组件中返回附加数据

c# - 模拟命令行的控制台应用程序

c# - SingleResult.Create 在空 IQueryable 上的 Odata 序列化错误

c# - 从按下的按钮获取返回值

c# - 更改页面时如何从下拉列表中保留所选值?