首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用windows身份验证管理mvc 5中角色的最佳方法

使用windows身份验证管理mvc 5中角色的最佳方法
EN

Stack Overflow用户
提问于 2015-07-20 14:14:01
回答 1查看 784关注 0票数 0

我正在构建一个基于intranet的应用程序,如下所示,并需要关于管理用户角色的最佳方法的建议。

  1. MVC 5 windows身份验证内部网应用程序。
  2. 无法使用AD的角色将需要管理与应用程序。
  3. 只有3个角色,管理员,主管,用户,将在应用程序中维护。
  4. 向角色添加/删除用户的能力
  5. 将使用AD获取用户姓名和电子邮件,然后在应用程序中持久化。
  6. 我使用实体框架6和sql服务器(这不会改变)

我不确定是否创建自己的自定义方法来管理角色,而不是使用asp.net标识方法或任何其他方法。

我在想,由于它是一个相对简单的应用程序,我可能只是使用我自己的方法?

EN

回答 1

Stack Overflow用户

发布于 2015-07-20 14:48:45

嗯,

这是工作,但如果是我,我会使用Windows身份基金会(WIF 4.5)。我将创建一个自定义安全令牌服务和安全令牌配置类。

第一:

在EF中构建两个名为Roles和UsersInRoles的表。

角色

  1. 自动增量( RoleId )
  2. 角色(varchar(255))

角色用户

  1. UserName (varchar(255),唯一主键)
  2. RoleId (外键角色-> RoleId)

Wif:

步骤1:

创建一个单独的项目来构建登录站点,一个新的空MVC站点。配置web.config以使用NTLM进行身份验证,并为其删除匿名访问。给它一个像login.mysite.com一样的网址。

创建STS、STS配置和CertificateUtil:

代码语言:javascript
复制
public class XYZSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
{
    static readonly object syncRoot = new object();
    static string stsKey = "XYZSecurityTokenServiceConfiguration";


    public static XYZSecurityTokenServiceConfiguration Current
    {
        get
        {
            HttpApplicationState httpAppState = HttpContext.Current.Application;
            XYZSecurityTokenServiceConfiguration myConfiguration = httpAppState.Get(stsKey) as XYZSecurityTokenServiceConfiguration;
            if (myConfiguration != null)
            {
                return myConfiguration;
            }
            lock (syncRoot)
            {
                myConfiguration = httpAppState.Get(stsKey) as XYZSecurityTokenServiceConfiguration;
                if (myConfiguration == null)
                {
                    myConfiguration = new XYZSecurityTokenServiceConfiguration();
                    httpAppState.Add(stsKey, myConfiguration);
                }
                return myConfiguration;
            }
        }
    }

    public XYZSecurityTokenServiceConfiguration() : base("XYZPassiveSTS", CertificateUtil.SigningCreds)
    {
        this.SecurityTokenService = typeof(TLCSecurityTokenService);
    }
}


public class XYZSecurityTokenService : SecurityTokenService
{
    public XYZSecurityTokenService(SecurityTokenServiceConfiguration configuration)
        : base(configuration)
    {                        
    }

    void ValidateAppliesTo(EndpointReference appliesTo)
    {
        if (appliesTo == null)
        {
            throw new ArgumentNullException("appliesTo");
        }
    }

    protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request)
    {
        ValidateAppliesTo(request.AppliesTo);

        Scope scope = new Scope(
            request.AppliesTo.Uri.OriginalString,
            SecurityTokenServiceConfiguration.SigningCredentials);
        scope.TokenEncryptionRequired = false;

        scope.ReplyToAddress = scope.AppliesToAddress;
        //scope.ReplyToAddress = request.ReplyTo;

        return scope;
    }

    protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
    {
        //We Can Add Additonal Claims Here!
        ClaimsIdentity claims = new ClaimsIdentity();
        claims.AddClaims(principal.Claims);
        string userName = principal.Identity.Name;

        //Use EF To get user's roles by userName,

        var roles = DBContext.GetRolesForUser(userName);
        foreach (var role in roles)
        {
           Claim roleClaim = new Claim(ClaimTypes.Role, role.Role, ClaimValueTypes.String);
           claims.AddClaims(roleClaim);
        }
    }
}

public class CertificateUtil
{
    #region Fields
    private const string SIGNING_CERTIFICATE_NAME = "CN=TokenSigningCert";
    private const string ENCRYPTING_CERTIFICATE_NAME = "CN=TokenSigningCert";
    private static SigningCredentials _signingCreds = null;
    private static EncryptingCredentials _encryptingCreds = null;
    #endregion

    #region Properties
    public static SigningCredentials SigningCreds
    {
        get
        {
            if (_signingCreds == null)
                _signingCreds = new X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, SIGNING_CERTIFICATE_NAME));
            return _signingCreds;
        }
    }
    public static EncryptingCredentials EncryptingCreds
    {
        get
        {
            if (_encryptingCreds == null)
                _encryptingCreds = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, ENCRYPTING_CERTIFICATE_NAME));
            return _encryptingCreds;
        }
    }

    #endregion

    /// <summary>
    /// Get the certificate from a specific store/location/subject.
    /// </summary>
    private static X509Certificate2 GetCertificate(StoreName name, StoreLocation location, string subjectName)
    {
        X509Store store = new X509Store(name, location);
        X509Certificate2Collection certificates = null;
        store.Open(OpenFlags.ReadOnly);

        try
        {
            X509Certificate2 result = null;

            //
            // Every time we call store.Certificates property, a new collection will be returned.
            //
            certificates = store.Certificates;

            for (int i = 0; i < certificates.Count; i++)
            {
                X509Certificate2 cert = certificates[i];

                if (cert.SubjectName.Name.ToLower() == subjectName.ToLower())
                {
                    if (result != null)
                    {
                        throw new ApplicationException(string.Format("More than one certificate was found for subject Name {0}", subjectName));
                    }

                    result = new X509Certificate2(cert);
                }
            }

            if (result == null)
            {
                throw new ApplicationException(string.Format("No certificate was found for subject Name {0}", subjectName));
            }

            return result;
        }
        finally
        {
            if (certificates != null)
            {
                for (int i = 0; i < certificates.Count; i++)
                {
                    X509Certificate2 cert = certificates[i];
                    cert.Reset();
                }
            }

            store.Close();
        }
    }
}

在登录站点中,还需要一个控制器来处理登录和注销。

现在,您将使用NTLM,因此对站点的任何请求都将进行身份验证,如果关闭匿名访问,他们将无法在未登录NTLM的情况下访问该站点。

因此,您的控制器只需要执行进程请求,

代码语言:javascript
复制
if (!Request.IsAuthenticated)
    return RedirectToAction("SomethingBroke");

CasPrincipal cp = User as CasPrincipal;
ClaimsPrincipal p = new ClaimsPrincipal(cp.Identity);
               FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(System.Web.HttpContext.Current.Request, p, WIF.TLCSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService(), System.Web.HttpContext.Current.Response);

WIF由查询字符串参数驱动,不同的参数控制进程请求的操作。如果查询有wssignin参数,那么它将登录并重定向回主站点。如果它有wssignout,它将签出并重定向回来。

现在,回到您的主站点,添加依赖于wif登录站点的web.cofnig条目,

代码语言:javascript
复制
<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" />
  </configSections>
  <system.webServer>
    <modules>
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <add name="WSFederatedAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </modules>
  </system.webServer>
  <system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <trustedIssuers>
          <!-- Use MMC and the Certificate Snapin to get the thumbprint for your certificate.  It will be different on other machines and this value might not work as is from source control.-->
          <add thumbprint="97f983a05587253b6835d1bd0062000c5d1f398d" name="TokenSigningCert" />
        </trustedIssuers>
      </issuerNameRegistry>
      <audienceUris mode="Never" />
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration identityConfigurationName="">
      <serviceCertificate>
        <certificateReference x509FindType="FindBySubjectName" findValue="TokenSigningCert" storeLocation="LocalMachine" storeName="TrustedPeople" />
      </serviceCertificate>
      <wsFederation passiveRedirectEnabled="true" issuer="http://login.example.com" realm="http://example.com" requireHttps="false" />
      <cookieHandler requireSsl="false" mode="Default">
        <chunkedCookieHandler chunkSize="2000" />
      </cookieHandler>
    </federationConfiguration>
  </system.identityModel.services>  
</configuration>

最后,在您的主站点中,您需要一个处理登录和注销的控制器。

你这么做的时候

代码语言:javascript
复制
                //To Log In
            FederatedAuthentication.WSFederationAuthenticationModule.RedirectToIdentityProvider("MYSiteIDYouMakeUpHere", "TheUrlToReturnToAfterLoginHere", true);

            //ToLogOut
            var issuer = FederatedAuthentication.FederationConfiguration.WsFederationConfiguration.Issuer;
            var signOutUrl = WSFederationAuthenticationModule.GetFederationPassiveSignOutUrl(issuer, "returnurlhere", null);
            Redirect(signOutUrl);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31518817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档