zoukankan      html  css  js  c++  java
  • ABP集成WIF实现单点登录

    ABP集成WIF实现单点登录

    参考

    ojlovecd写了三篇关于WIF文章。

    使用WIF实现单点登录Part III —— 正式实战 

    使用WIF的一些开源示例。

    https://github.com/obhita/PROCenter/tree/master/ProCenter.LocalSTS/STS

    https://github.com/primaryobjects/SingleSignOn

    https://github.com/shinpou/Windows-Identity-Foundation-Tutorial/tree/master/Learning%20SSO

    WSFederation and SAML library for Java based web applications

    https://github.com/auth10/auth10-java

    WIF配置过程中的一些问题

    1、WIF授权

    MVC项目中使用[Authorize],注解方式鉴权。

    webform项目中使用配置文件方式鉴权。

    <system.web>
         <authorization>
            <deny users="?" />
          </authorization>
    </system.web>
    View Code

    2、密钥集合不存在

    Exception: System.Security.Cryptography.CryptographicException
    Message: 密钥集不存在。

    解决方法:

    C:Documents and SettingsAll UsersApplication DataMicrosoftCryptoRSAMachineKeys这个目录授权的时候出错了,一直报这个错误
    “将安全信息应用到以下对象时发生错误 拒绝访问”,为ereryone用户分配完全控制权限,密钥集的错误就解决了。

    3、部署时,出现

    用户代码未处理 System.Security.Cryptography.CryptographicException 错误解决方法

    解决方法:

    IIS 应用程序池--选中你网站的所配置的应用程序池--右键 选择 “高级配置” --将“加载用户配置文件” 设置为True 。

    4、thumbprint值

    配置文件中<add thumbprint="xxxxxxxxxx" name="sts" />的值,使用IIS服务器证书中的指纹值。复制粘贴会带一些特殊字符,还是手敲吧!

    在ABP中集成

    User.Identity && User.Identity.IsAuthenticated并不依赖Session。
    Web.config文件设置或者浏览器请求时候删除ASP.NET_SessionId只要保留.AspNet.ApplicationCookie存在请求身份一样能通过验证。
    <system.web>
        <sessionState mode="Off" />
    </system.web>

    RP站

    RP OnAuthentication鉴权:

            protected override void OnAuthentication(AuthenticationContext filterContext)
            {
                if (filterContext.HttpContext == null)
                    throw new ArgumentNullException("httpContext");
                IPrincipal user = filterContext.HttpContext.User;
    
                bool isFederation = false;
                bool isApp = false;
                IEnumerable<ClaimsIdentity> cl = ((ClaimsPrincipal)User).Identities;
                if (cl != null && cl.Count() > 0)
                {
                    foreach (var item in cl)
                    {
                        if (item.AuthenticationType.Equals("Federation") && item.IsAuthenticated)
                        {
                            isFederation = true;
                        }
                        else if (item.AuthenticationType.Equals("ApplicationCookie") && item.IsAuthenticated)
                        {
                            isApp = true;
                            if (item.Claims.Where(p => p.Type == "SSO-Login").Count() == 0)
                                isFederation = true;
                        }
                    }
                }
                if (!isFederation || !isApp)
                    filterContext.Result = new RedirectResult("/Account/Login");
    
                if (!user.Identity.IsAuthenticated || !AbpSession.UserId.HasValue)
                    filterContext.Result = new RedirectResult("/Account/Login");
            }

    RP登录:

            public async Task<ActionResult> Login(string userNameOrEmailAddress = "", string returnUrl = "", string successMessage = "")
            {
                bool isFederation = false, isApp = false;
                var identities = ((ClaimsPrincipal)User).Identities;
                if(identities!=null && identities.Count() > 0)
                {
                    var federation = identities.Where(p => p.AuthenticationType == "Federation").FirstOrDefault();
                    if (federation != null)
                        isFederation = federation.IsAuthenticated;
    
                    var applicationCookie = identities.Where(p => p.AuthenticationType == "ApplicationCookie").FirstOrDefault();
                    if (applicationCookie != null)
                        isApp = applicationCookie.IsAuthenticated;
                }
                if (!isFederation)
                {
                    FederatedAuthentication.WSFederationAuthenticationModule.SignIn(null);
                    return null;
                }
                //创建本地abpsession
                if (!isApp)
                {
                    string name = string.Empty, role = string.Empty;
                    ClaimsIdentity claims = User.Identity as ClaimsIdentity;
                    if (claims != null)
                    {
                        var list = claims.Claims.ToList();
                        if (list != null && list.Count > 0)
                        {
                            var cName = claims.Claims.Where(p => p.Type == ClaimTypes.Name).FirstOrDefault();
                            if (cName != null)
                                name = cName.Value;
                            var cRole = claims.Claims.Where(p => p.Type == ClaimTypes.Role).FirstOrDefault();
                            if (cRole != null)
                                role = cRole.Value;
    
                            var cEmail = claims.Claims.Where(p => p.Type == ClaimTypes.Email).FirstOrDefault();
                            if (cEmail != null)
                                name = cEmail.Value;
    
                            if (name.Contains("\"))
                                name = name.Replace("\", "");
                            if (string.IsNullOrEmpty(role))
                                role = ConfigHelper.GetAppSetting("UserRole");
                        }
                    }
                    var user = _userIdentity.GetUserByName(name);
                    if (user == null)
                    {
                        CreateOrUpdateUserInput input = new CreateOrUpdateUserInput();
                        input.User = new UserEditDto();
                        input.User.Name = name;
                        input.User.Surname = input.User.Name;
                        input.User.UserName = input.User.Name;
                        input.User.Password = Infrastructure.Authorization.Users.User.CreateRandomPassword();
                        input.User.EmailAddress = name + "@xx.com";
                        input.AssignedRoleNames = new string[] { role };
    
                        user = await _userIdentity.CreateUserAsync(input);
                    }
                    await SignInAsync(user);
                }
                return RedirectToAction("Index", "Home");
            }

    RP 登出:

            public ActionResult Logout()
            {
                IEnumerable<ClaimsIdentity> cis = ((ClaimsPrincipal)User).Identities;
                if (cis != null && cis.Count() > 0)
                {
                    foreach (var item in cis)
                    {
                        if (item.AuthenticationType.Equals("Federation"))
                        {
                            var authModule = FederatedAuthentication.WSFederationAuthenticationModule;
                            WSFederationAuthenticationModule.FederatedSignOut(new Uri(authModule.Issuer + "/Account/Logout"), new Uri(authModule.Reply));
                        }
                        else if (item.AuthenticationType.Equals("ApplicationCookie"))
                        {
                            _authenticationManager.SignOutAll();
                        }
                    }
                }
                return RedirectToAction("Login");
            }

    STS认证成功后回调RP(host:www.test.com)会传入如下信息
    将信息.AspNet.ApplicationCookie、FedAuth、FedAuth1复制后使用其它浏览器写入这三个Cookie刷新可正常验证用户信息。
    FedAuth、FedAuth1是WIF STS给的认证信息。

    如果访问的子站点(www.test.com)没有通过STS将认证(FedAuth、FedAuth1)信息回写到子站点的Cookie中,此时使用其它已认证的子站点(FedAuth、FedAuth1)信息模拟到www.test.com站点是无法识别的。

    WIF认证服务端:

    CustomSecurityTokenService.cs

            protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
            {
                //WIF返回Claims中信息,里面了包含自己想要的声明
                ClaimsIdentity outgoingIdentity = new ClaimsIdentity();
                var claims = principal.Claims.ToList();
                foreach(var item in claims)
                {
                    if(item.Type != "AspNet.Identity.SecurityStamp" && item.Type != ClaimTypes.NameIdentifier)
                    {
                        outgoingIdentity.AddClaim(new Claim(item.Type, item.Value));
                    }
                }
                SingleSignOnManager.RegisterRP(scope.AppliesToAddress);
                return outgoingIdentity;
            }

    将Claims信息调用RP站管道信息带入到RP站:

            [UnitOfWork]
            public ActionResult Index()
            {
                FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(
                    System.Web.HttpContext.Current.Request,
                    User as ClaimsPrincipal,
                    CustomSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService(),
                    System.Web.HttpContext.Current.Response);
                var loginInfo = AsyncHelper.RunSync(() => _sessionAppService.GetCurrentLoginInformations());
                return View(loginInfo);
            }

    服务端登录的用户信息。

    登出只对当前机器当前使用的浏览器生效。实质是浏览器对已访问的子站点遍历wsignoutcleanup1.0。
    <img src="@(address)?wa=wsignoutcleanup1.0" style="display:none;" />
  • 相关阅读:
    vue中的样式
    v-model 双向数据绑定
    v-on 事件修饰符
    Linq Join
    Elasticsearch.Net 异常:[match] query doesn't support multiple fields, found [field] and [query]
    MongoDB开启权限认证
    elasticsearch备份与恢复
    elasticserach + kibana环境搭建
    Kibana TypeError : Object #<GlobalState> has no method 'setDefaults'
    匿名函数
  • 原文地址:https://www.cnblogs.com/ddrsql/p/7151777.html
Copyright © 2011-2022 走看看