>

앱에서 인증 및 권한 부여를 위해 SimpleMembership을 사용하는 Asp.net 4.5 MVC5 앱이 있습니다. 이제 인증을 위해 외부 IdentityServer4를 사용하도록 통합해야합니다. OWIN 시작 파일을 프로젝트에 추가하고 web.config에서 표준 IIS 인증을 해제하려고했습니다. 이제 로그인 및 동의를 위해 IDServer로 리디렉션 될 수 있습니다.

보기에 도달하면 문제가 발생했습니다 :

오류 메시지 :

No user found was found that has the name "". Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: No user found was found that has the name "".

Source Error:

Line 15: @if (Model != null) Line 16: { Line 17:
foreach (var claim in Model) Line 18: { Line 19:

@claim.Type

Source File: e:\GitHub\CRURepoPostBR20190607_IS4\CRU_Build\Suite\Views\Home\IS4Auth.cshtml Line: 17

Stack Trace: [InvalidOperationException: No user found was found that has the name "".]
WebMatrix.WebData.SimpleRoleProvider.GetRolesForUser(String username) +498 System.Web.Security.RolePrincipal.GetRoles() +215 System.Web.Security.d__4.MoveNext() +58
System.Security.Claims.d__51.MoveNext() +253
System.Security.Claims.d__37.MoveNext() +209

My IdentityServer는 IdentityServer4 빠른 시작 샘플의 복제본입니다. 내 MVC5 앱이 오래되었으며 인증 및 역할 인증에 SimpleMembership을 사용합니다. OWIN Startup.cs를 수동으로 추가했습니다. 아래 코드를 참조하십시오.

IdentityServer https://demo.identityserver.io 를 IDServer로 사용하려고 시도했지만 동일한 문제가 발생했습니다. 이것은 내 IDServer에 문제가 없음을 증명했습니다.

SimpleMembership없이 간단한 별도의 Asp.net 4.5 MVC5 프로젝트를 만들려고했지만 오류가 발생하지 않습니다.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });
        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            AuthenticationType = "oidc",
            SignInAsAuthenticationType = "Cookies",
            ClientSecret = "secret",
            //Authority = "http://localhost:5000", //ID Server
            Authority = "https://demo.identityserver.io", //ID Server
            RequireHttpsMetadata = false,
            RedirectUri = "http://localhost:58018/signin-oidc",
            //RedirectUri = "http://localhost:58018/",
            //ClientId = "myOldMvc",
            ClientId = "server.hybrid",
            ResponseType = "id_token code",
            Scope = "openid profile",
        });
        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
    }
}

청구서를 표시하는보기는 다음과 같습니다.

@model IEnumerable<System.Security.Claims.Claim>
@{
    ViewBag.Title = "IS4Auth";
}
<h2>IS4Auth</h2>
<dl>
    @if (Model != null)
    {
        foreach (var claim in Model)
        {
            <dt>@claim.Type</dt>
            <dd>@claim.Value</dd>
        }
    }
</dl>

여기서는 system.web 및 system.webServer에 대한 설정 관련 부분이 있습니다

<system.web>
    <httpModules>
      <add name="ar.sessionscope" type="Castle.ActiveRecord.Framework.SessionScopeWebModule, Castle.ActiveRecord.web" />
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
    </httpModules>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" maxRequestLength="1048576" />
    <!--Change for IS4Authentication-->
    <authentication mode="None" />
    <!--<authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>-->
    <!--<roleManager enabled="true" defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleRoleProvider,WebMatrix.WebData" />
      </providers>
    </roleManager>
    <membership defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider,WebMatrix.WebData" enablePasswordReset="true" requiresQuestionAndAnswer="false" />
      </providers>
    </membership>-->
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <httpHandlers>
      <add verb="*" path="routes.axd" type="AttributeRouting.Web.Logging.LogRoutesHandler, AttributeRouting.Web" />
      <add verb="POST,GET,HEAD" path="elmah" type="Elmah.ErrorLogPageFactory, Elmah" />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <add name="Elmah" verb="POST,GET,HEAD" path="elmah" type="Elmah.ErrorLogPageFactory, Elmah" />
    </handlers>
    <modules>
      <!--Change for IS4Authentication-->
      <remove name="FormsAuthentication" />
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="X-UA-Compatible" value="IE=Edge" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

OpenIdConnectAuthenticationOptions에 추가 된 알림 코드는 다음과 같습니다

   Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            "http://localhost:5000/connect/token",
                            //"server.hybrid",
                            "myApp",
                            "secret");
                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
                        if (tokenResponse.IsError)
                        {
                            //throw new Exception(tokenResponse.Error);
                            throw new AuthenticationException(tokenResponse.Error);
                        }
                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient("http://localhost:5000/connect/userinfo");
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);
                        var Name = userInfoResponse.Claims.FirstOrDefault(c => c.Type.Equals("Name", StringComparison.CurrentCultureIgnoreCase)).Value;
                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, JwtClaimTypes.Name, JwtClaimTypes.Role),
                            n.AuthenticationTicket.Properties
                        );
                        List<Claim> _claims = new List<Claim>();
                        _claims.AddRange(new List<Claim>
                        {
                            new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Name),
                            new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",Name)
                        });
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType != OpenIdConnectRequestType.Logout)
                        {
                            return Task.FromResult(0);
                        }
                        var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
                        if (idTokenHint != null)
                        {
                            n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        }
                        return Task.FromResult(0);
                    }
         } 

  • 답변 # 1

    d_f의 잠깐만 기다려 주셔서 감사합니다. 문제가 해결되었습니다. 해결 방법은 알림을 사용하여 userInfo EndPoint에서 클레임을 명시 적으로 검색하여 새 ID에 추가하는 것입니다. Notifications = new OpenIdConnectAuthenticationNotifications {}

    에서 위 코드를 참조하십시오.

관련 자료

  • 이전 postgresql - DB2에서 postgres로
  • 다음 글꼴 크기를 제한하기 위해 CSS 글꼴 크기 계산을 수정하는 방법