tl;dr - GitHub 上的演示项目
下面的步骤可能看起来很长,但实际上非常简单。我只用了一个小时左右就创建了我的演示项目。
我同意你关于使用 Owin 和 Katana 的观点。我以前经历过这个过程,但这并不是一次很棒的经历。使用 Firebase 就容易多了。
这一切都可以通过 JWT 来完成!
当您通过 Firebase 和任何社交提供商进行身份验证时,您会得到一个 JSON Web 令牌 (JWT) -firebaseAuthToken
.
从仪表板获取您的 Firebase 秘密
JWT 的工作方式是我们有一个秘密令牌和一个客户端令牌。客户端令牌是我们登录后收到的 firebaseAuthToken。秘密令牌是在 Firebase 仪表板中为我们生成的。
将您的 Firebase Secret 存储在 Web.config 的 appSettings 部分中
我们需要将此密钥存储在 Web.config 中,以便以后更容易访问。
<add key="FirebaseSecret" value="<Firebase-Secret-Token-Goes-Here" />
创建操作过滤器以检查授权标头中的 JWT
我们可以通过在授权标头中传递客户端令牌来验证请求是否有效。在服务器上,我们可以存储从 Firebase 仪表板获取的密钥。当 Web API 检查请求时,我们可以使用 JWT 库对 JWT 进行解码(可从 NuGet 获得)。如果解码成功,那么我们可以检查令牌以确保它没有过期。
public class DecodeJWT: ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string firebaseAuthToken = string.Empty;
if (actionContext.Request.Headers.Authorization != null) {
firebaseAuthToken = actionContext.Request.Headers.Authorization.Scheme;
} else {
throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
}
string secretKey = WebConfigurationManager.AppSettings["FirebaseSecret"];
try {
string jsonPayload = JWT.JsonWebToken.Decode(firebaseAuthToken, secretKey);
DecodedToken decodedToken = JsonConvert.DeserializeObject < DecodedToken > (jsonPayload);
// TODO: Check expiry of decoded token
} catch (JWT.SignatureVerificationException jwtEx) {
throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
} catch (Exception ex) {
throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
}
base.OnActionExecuting(actionContext);
}
}
创建一个 $http 拦截器,将 firebase AuthToken 添加到每个请求的标头中
在客户端,技巧是每次都必须传递令牌。为了使这更容易,我们需要创建一个$httpInterceptor
与 Angular 一起检查firebaseAuthToken
on sessionStorage
.
.factory('authInterceptor', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.firebaseAuthToken) {
config.headers.Authorization = $window.sessionStorage.firebaseAuthToken;
}
return config;
},
response: function (response) {
if (response.status === 401) {
// TODO: User is not authed
}
return response || $q.when(response);
}
};
})
成功登录后将 firebaseAuthToken 设置为 sessionStorage
每当用户登录时,我们可以将该值设置为sessionStorage
.
$rootScope.$on('$firebaseSimpleLogin:login',
function (e, user) {
// add a cookie for the auth token
if (user) {
$window.sessionStorage.firebaseAuthToken = user.firebaseAuthToken;
}
cb(e, user);
});
全局注册 DecodeJWT 过滤器
里面的WebApiConfig.cs
通过注册方法,我们可以设置 DecodeJWT 过滤器以应用于所有 ApiController。
config.Filters.Add(new DecodeJWT());
现在,每当我们向 ApiController 发出请求时,除非存在有效的 JWT,否则它都会拒绝该请求。因此,在用户登录后,如果 ApiController 不存在,我们可以将其数据保存到该 ApiController 中。
// globally uses DecodeJWT
public class UsersController: ApiController
{
// POST api/users
public void Post([FromBody] FbUser user) // See GitHub for this Model
{
// Save user if we do not already have it
}
}