以下步骤可能看起来很长,但实际上非常简单。我只用了一个小时左右就创建了我的演示项目。
我同意你关于使用 Owin 和 Katana 的观点。我以前经历过这个过程,这并不是一个很好的经历。使用 Firebase 要容易得多。
这一切都可以通过 JWT 完成!
当您通过 Firebase 和任何社交服务提供商进行身份验证时,您会得到一个 JSON Web 令牌 (JWT) - firebaseAuthToken。
从仪表板获取您的 Firebase 机密
JWT 的工作方式是我们有一个秘密令牌和一个客户端令牌。客户端令牌是我们登录后收到的 firebaseAuthToken。秘密令牌是在 Firebase Dashboard 中为我们生成的。
将您的 Firebase Secret 存储在 Web.config 的 appSettings 部分中
我们需要将此密钥存储在 Web.config 中,以便以后访问。
<add key="FirebaseSecret" value="<Firebase-Secret-Token-Goes-Here" />
创建一个操作过滤器以检查来自授权标头的 JWT
我们可以通过在 Authorization 标头中传递客户端令牌来验证请求是否有效。在服务器上,我们可以存储从 Firebase 仪表板获得的密钥。当 Web API 检查请求时,我们可以使用 JWT 库 (available from NuGet) 解码 JWT。如果解码成功,那么我们可以检查令牌以确保它没有过期。
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);
}
}
创建一个 $httpInterceptor 将 firebaseAuthToken 添加到每个请求的标头中
在客户端,诀窍是每次都必须传递令牌。为了使这更容易,我们需要使用 Angular 创建一个 $httpInterceptor 来检查 sessionStorage 上的 firebaseAuthToken。
.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 Register 方法中,我们可以设置 DecodeJWT 过滤器以应用于我们所有的 ApiController。
config.Filters.Add(new DecodeJWT());
现在,每当我们向 ApiController 发出请求时,它都会拒绝它,除非有有效的 JWT。因此,在用户登录后,如果 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
}
}