我有一个ASP.NET MVC 4应用程序,我正在尝试实现基于声明的身份验证和授权 . 我们有一个SSO代理,在标头中插入有关用户的某些信息(例如用户名) . 我已经实现了自己的ClaimsAuthenticationManager,我想要做的是从头文件中获取用户名,创建一个包含UserName声明的ClaimsPrinsipal,将其传递给我的ClaimsAuthenticationManager,它将命中数据库以确定用户应该拥有的角色,并使用角色声明填充主体 . 然后我想在用户会话的其余部分使用转换后的声明 .
到目前为止我所拥有的:
Web.config:
<配置>
...
在<system.web>
...
<authentication mode =“Forms”> <forms loginUrl =“〜/ Account / Authorize”timeout =“20”/> </认证> </system.web> </配置>
MyClaimsTransformer.cs
public class MyClaimsTransformer : ClaimsAuthenticationManager
{
private readonly IAuthenticationUow _authenticationUow;
private readonly IWebServiceUrls _webServiceUrls;
public MyClaimsTransformer(IAuthenticationUow authenticationUow, IWebServiceUrls webServiceUrls)
{
_authenticationUow = authenticationUow;
_webServiceUrls = webServiceUrls;
}
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal == null || incomingPrincipal.Identity == null || !incomingPrincipal.Identity.IsAuthenticated)
throw new SecurityException("No claims principal or not authenticated");
var userName = incomingPrincipal.Identity.Name;
if (string.IsNullOrWhiteSpace(userName))
throw new SecurityException("No user name found");
// Add role claims
return incomingPrincipal;
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
FederatedAuthentication.FederationConfigurationCreated += FederatedAuthentication_FederationConfigurationCreated;
}
private void FederatedAuthentication_FederationConfigurationCreated(object sender, System.IdentityModel.Services.Configuration.FederationConfigurationCreatedEventArgs e)
{
WebServiceUrls serviceUrls = new WebServiceUrls();
AppProperties appProperties = new AppProperties();
serviceUrls.UserNameWebServiceUrl = appProperties.UserNameWebServiceUrl;
serviceUrls.PointOfContactWebServiceUrl = appProperties.PointOfContactWebServiceUrl;
e.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager =
ObjectFactory.With<IWebServiceUrls>(serviceUrls).GetInstance<MyClaimsTransformer>();
}
}
AccountController.cs
[Authorize]
public class AccountController : BaseController
{
[AllowAnonymous]
public ActionResult Authorize(string returnUrl)
{
string userId = Request.Headers["userid"];
if (Url.IsLocalUrl(returnUrl))
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, userId)
};
var id = new ClaimsIdentity(claims, "Custom", ClaimTypes.Name, ClaimTypes.Role);
var principal = new ClaimsPrincipal(id);
// call out to registered ClaimsAuthenticationManager
var claimsAuthManager = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
// set the transformed principal
var url = Request.Url;
if (url != null)
{
var newPrincipal = claimsAuthManager.Authenticate(url.AbsolutePath, principal);
SetSessionCookie(newPrincipal);
Thread.CurrentPrincipal = newPrincipal;
}
return Redirect(returnUrl);
}
throw new InvalidDataException("BAD URL");
}
private void SetSessionCookie(ClaimsPrincipal incomingPrincipal)
{
SessionSecurityToken token = new SessionSecurityToken(incomingPrincipal);
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
}
}
此代码运行正常,当执行 Thread.CurrentPrincipal = newPrincipal;
行时,所有正确的声明都在主体中 . 但是,当我使用我的自定义ClaimsAuthorizationManager检查声明时,它们都不存在(同样,Principal不再经过身份验证) . 它只是重新指向AccountController再次进行身份验证 .
我错过了什么?
1 回答
在Authenticate覆盖中,您应该将incomingPrincipal路由到基本的ClaimsAuthenticationManager: