最后,在阅读了很多之后,我有这个:
在 AngularJS 中:
'use strict';
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var serviceBase = 'http://localhost:64346/';
var authServiceFactory = {};
var _authData = localStorageService.get('authorizationData');
var _authentication = {
isAuth: _authData != null? true : false,
userName: _authData != null ? _authData.userName : ""
};
var _saveRegistration = function (registration) {
_logOut();
return $http.post(serviceBase + 'api/account/register', registration).then(function (response) {
return response;
});
};
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'api/authorization', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
var _logOut = function () {
$http.delete(serviceBase + 'api/authorization').success(function() {
localStorageService.remove('authorizationData');
_authentication.isAuth = false;
_authentication.userName = "";
});
};
var _fillAuthData = function () {
var authData = localStorageService.get('authorizationData');
if (authData) {
_authentication.isAuth = true;
_authentication.userName = authData.userName;
}
}
authServiceFactory.saveRegistration = _saveRegistration;
authServiceFactory.login = _login;
authServiceFactory.logOut = _logOut;
authServiceFactory.fillAuthData = _fillAuthData;
authServiceFactory.authentication = _authentication;
return authServiceFactory;
}]);
在 WebApi 中:
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Services;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Web.Http;
using System.Xml;
using Thinktecture.IdentityModel.Constants;
using Thinktecture.IdentityModel.WSTrust;
using WebApi_AngularJs.Model;
namespace WebApi_AngularJs.Controllers
{
public class AuthorizationController : ApiController
{
// GET: api/Authorization
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Authorization/5
[Authorize]
public string Get(int id)
{
return "value";
}
// POST: api/Authorization
public LoginResponse Post([FromBody]Login data)
{
var credentials = new ClientCredentials();
credentials.UserName.UserName = data.UserName;
credentials.UserName.Password = data.Password;
ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true;
var claims = GetClaimsFromIdentityServer(data.UserName, data.Password);
var response = new LoginResponse();
if (claims != null)
{
//All set so now create a SessionSecurityToken
var token = new SessionSecurityToken(claims)
{
IsReferenceMode = true //this is
//important.this is how you say create
//the token in reference mode meaning
//your session cookie will contain only a
//referenceid(which is very small) and
//all claims will be stored on the server
};
FederatedAuthentication.WSFederationAuthenticationModule.
SetPrincipalAndWriteSessionToken(token, true);
response = new LoginResponse { access_token = token.Id , data = "data"};
}
return response;
}
// PUT: api/Authorization/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/Authorization/
public void Delete()
{
//clear local cookie
FederatedAuthentication.SessionAuthenticationModule.SignOut();
FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(false);
}
private ClaimsPrincipal GetClaimsFromIdentityServer(string username, string password)
{
const string WS_TRUST_END_POINT = "https://srv:4443/issue/wstrust/mixed/username";
var factory = new System.ServiceModel.Security.WSTrustChannelFactory
(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
string.Format(WS_TRUST_END_POINT));
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
var rst = new System.IdentityModel.Protocols.WSTrust.RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
TokenType = TokenTypes.Saml2TokenProfile11,
AppliesTo = new EndpointReference
("urn:webapisecurity")
};
var st = factory.CreateChannel().Issue(rst);
var token = st as GenericXmlSecurityToken;
var handlers = FederatedAuthentication.FederationConfiguration.
IdentityConfiguration.SecurityTokenHandlers;
var token = handlers.ReadToken(new XmlTextReader
(new StringReader(token.TokenXml.OuterXml))) as Saml2SecurityToken;
var identity = handlers.ValidateToken(token).First();
var principal = new ClaimsPrincipal(identity);
return principal;
}
}
}
在 Web.Config 中:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301879
-->
<configuration>
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ida:FederationMetadataLocation" value="https://srv:4443/FederationMetadata/2007-06/FederationMetadata.xml" />
<add key="ida:Realm" value="urn:webapisecurity" />
<add key="ida:AudienceUri" value="urn:webapisecurity" />
<add key="AppName" value="Web API Security Sample" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<modules>
<add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
<system.identityModel>
<identityConfiguration>
<audienceUris>
<add value="urn:webapisecurity" />
</audienceUris>
<claimsAuthorizationManager type="Thinktecture.IdentityServer.Ofi.AuthorizationManager, Thinktecture.IdentityServer.Ofi, Version=1.0.0.0, Culture=neutral" />
<claimsAuthenticationManager type="Thinktecture.IdentityServer.Ofi.AuthenticationManager, Thinktecture.IdentityServer.Ofi, Version=1.0.0.0, Culture=neutral" />
<certificateValidation certificateValidationMode="None" />
<issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<trustedIssuers>
<add thumbprint="489116B0FCF14DF66D47AE272C3B9FD867D0E050" />
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
</system.identityModel>
<system.identityModel.services>
<federationConfiguration>
<cookieHandler requireSsl="false" />
<wsFederation passiveRedirectEnabled="true" issuer="https://srv:4443/issue/wsfed" realm="urn:webapisecurity" reply="http://localhost:64346/" requireHttps="false" />
</federationConfiguration>
</system.identityModel.services>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
有了这个,我可以在浏览器中看到 FedAuth cookie 并在 WebApi 中进行验证。