我正在学习在WebApi中实现新的自定义中间件(外部登录)来验证用户。我使用空模板来了解实际情况。
我得到了一些不错的文章和外部登录自定义中间件提供商的链接来帮助我实现这一点。
- http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-angularjs-app/
- https://www.simple-talk.com/dotnet/net-framework/creating-custom-oauth-middleware-for-mvc-5/
- https://github.com/TerribleDev/OwinOAuthProviders
- https://katanaproject.codeplex.com/SourceControl/latest#README
基于这些文章,我完成了Github的自定义中间件,并成功地对用户进行了身份验证。
现在我需要了解webapi身份系统是如何验证用户的,以及外部声明是如何保存的。所以在从第三方成功登录后,我只创建了声明并调用SignIn方法。
到目前为止,一切都正常工作。
但在这之后,我试图使用访问令牌(即外部访问令牌)访问任何受保护的资源,但我只得到了未授权。我假设,由于我没有将用户注册到本地数据库,我可以使用相同的外部访问令牌来使用资源。
我试了两种方法。首先,在ExternalLogin方法本身中,我在签名后重定向到受保护的资源。接下来,我试着和其他客户合作。
我的身份验证配置代码:
[assembly: OwinStartup(typeof(CustomExternalLogin.Startup))]
namespace CustomExternalLogin
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
//Use Git authentication
app.UseGitAuthentication("myclientid", "myclientsecret");
}
}
}
我的控制器代码
[Authorize]
[RoutePrefix("api/Account")]
public class AccountController : ApiController
{
[OverrideAuthorization]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name ="ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
string redirectUri = string.Empty;
//Check any error and return
if(error != null)
{
return BadRequest(Uri.EscapeDataString(error));
}
//if not current user is authenticated return challengeresult so that middleware continue for external authentication
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider, this);
}
ClaimsIdentity externalIdentity = User.Identity as ClaimsIdentity;
Claim providerClaim = externalIdentity.FindFirst(ClaimTypes.NameIdentifier);
Claim userClaim = externalIdentity.FindFirst(ClaimTypes.Name);
string token = externalIdentity.FindFirstValue("ExternalAccessToken");
IEnumerable<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, providerClaim.Value, null, providerClaim.Issuer),
new Claim(ClaimTypes.Name, userClaim.Value, null, userClaim.Issuer)
};
ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
Authentication.SignIn(identity);
Uri currentUri = Request.RequestUri;
string home = currentUri.Scheme + Uri.SchemeDelimiter + currentUri.Authority + currentUri.Segments[0] + currentUri.Segments[1] + "Home/User?access_token=Bearer " + token ;
return Redirect(home);
}
#region Helpers
private IAuthenticationManager Authentication
{
get { return Request.GetOwinContext().Authentication; }
}
#endregion
}
}
我的受保护资源代码:
[Authorize]
[Route("User", Name ="User")]
public string GetUser()
{
var authentication = Request.GetOwinContext().Authentication;
return "Welcome " + User.Identity.Name;
}
请帮我找到我错过的地方
编辑1:
我得到了《时事》杂志。我尝试使用外部令牌访问。WebAPI Authorize使用local验证令牌,因此它总是失败。因此,解决方案是创建本地访问令牌,我就完成了。工作良好。
但目前我正在检查为什么Authentication.Signin()方法没有为我创建令牌?
最后我得到了它。从我的编辑中,我们可以理解需要本地令牌来验证用户。为此,我们可以使用Authentication.Signin()方法。
选项1:使用身份验证.Signin()
这里的要点是,这种身份验证使用cookie来保存信息,并使用承载令牌来对用户进行身份验证。因此,我们需要在auth-config 中包含以下行
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
OAuthOptions = new OAuthAuthorizationServerOptions
{
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
现在,令牌已成功生成并通过身份验证。这种方法的缺点是,它总是将令牌与url一起返回。对于纯api开发,最好返回json等
选项2:生成本地令牌并作为对象返回
在这里,我们可以简单地创建一个本地令牌,并像我们想要的那样作为对象返回。为此,我们可以使用OAuthBearerAuthenticationOptions。
需要在auth-config 中添加以下代码
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
之后,我们可以创建一个助手方法来创建本地令牌。这个方法已经解释过了,可以在下面的文章步骤9中找到。
http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-angularjs-app/
现在我很好。如果我的理解有任何错误,请解释