2015-06-11 2 views
7

मैं माफी माँगता हूँ की स्थापना के रूप में मैं सामान्य और विशेष रूप से IdentityServer में सुरक्षा का कोई ज्ञान के बगल में है।इस पूछने के लिए अग्रिम में IdentityServer wtih Asp.Net MVC आवेदन

मैं एक Asp.Net MVC अनुप्रयोग के लिए सुरक्षा का प्रबंधन करने के IdentityServer स्थापित करने के लिए कोशिश कर रहा हूँ।

मैं अपनी वेबसाइट पर ट्यूटोरियल अनुसरण कर रही हूं: Asp.Net MVC with IdentityServer

हालांकि, मैं कुछ है कि में थोड़ा अलग रहा पहचान "सर्वर" भाग के लिए एक अलग परियोजना है, जिसमें 2 Startup.cs फ़ाइलों की ओर जाता है है कर रहा हूँ, आवेदन के लिए एक और पहचान सर्वर

आवेदन के लिए के लिए एक, Startup.cs फ़ाइल लगता है कि यह

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject; 
     JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>(); 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = "Cookies" 
     }); 

     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      Authority = "https://localhost:44301/identity", 
      ClientId = "baseballStats", 
      Scope = "openid profile roles baseballStatsApi", 
      RedirectUri = "https://localhost:44300/", 
      ResponseType = "id_token token", 
      SignInAsAuthenticationType = "Cookies", 
      UseTokenLifetime = false, 
      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       SecurityTokenValidated = async n => 
       { 
        var userInfoClient = new UserInfoClient(
           new Uri(n.Options.Authority + "/connect/userinfo"), 
           n.ProtocolMessage.AccessToken); 

        var userInfo = await userInfoClient.GetAsync(); 

        // create new identity and set name and role claim type 
        var nid = new ClaimsIdentity(
         n.AuthenticationTicket.Identity.AuthenticationType, 
         Constants.ClaimTypes.GivenName, 
         Constants.ClaimTypes.Role); 

        userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2))); 

        // keep the id_token for logout 
        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); 

        // add access token for sample API 
        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken)); 

        // keep track of access token expiration 
        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString())); 

        // add some other app specific claim 
        nid.AddClaim(new Claim("app_specific", "some data")); 

        n.AuthenticationTicket = new AuthenticationTicket(
         nid, 
         n.AuthenticationTicket.Properties); 
       } 
      } 
     }); 

     app.UseResourceAuthorization(new AuthorizationManager()); 

     app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
     { 
      Authority = "https://localhost:44301/identity", 
      RequiredScopes = new[] { "baseballStatsApi"} 
     }); 

     var config = new HttpConfiguration(); 
     config.MapHttpAttributeRoutes(); 
     app.UseWebApi(config); 
    } 
} 

पहचान सर्वर के लिए, startup.cs फ़ाइल

है
public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.Map("/identity", idsrvApp => 
     { 
      idsrvApp.UseIdentityServer(new IdentityServerOptions 
      { 
       SiteName = "Embedded IdentityServer", 
       SigningCertificate = LoadCertificate(), 

       Factory = InMemoryFactory.Create(
        users: Users.Get(), 
        clients: Clients.Get(), 
        scopes: Scopes.Get()) 
      }); 
     }); 
    } 

    X509Certificate2 LoadCertificate() 
    { 
     return new X509Certificate2(
      string.Format(@"{0}\bin\Configuration\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test"); 
    } 
} 

मैं भी एक प्राधिकरण प्रबंधक

public class AuthorizationManager : ResourceAuthorizationManager 
{ 
    public override Task<bool> CheckAccessAsync(ResourceAuthorizationContext context) 
    { 
     switch (context.Resource.First().Value) 
     {      
      case "Players": 
       return CheckAuthorization(context); 
      case "About": 
       return CheckAuthorization(context); 
      default: 
       return Nok(); 
     } 
    } 

    private Task<bool> CheckAuthorization(ResourceAuthorizationContext context) 
    { 
     switch(context.Action.First().Value) 
     { 
      case "Read": 
       return Eval(context.Principal.HasClaim("role", "LevelOneSubscriber")); 
      default: 
       return Nok(); 
     } 
    } 
} 

की स्थापना कर रहा हूँ तो उदाहरण के लिए, अगर मैं एक नियंत्रक विधि है, तो

public class HomeController : Controller 
{ 

    [ResourceAuthorize("Read", "About")] 
    public ActionResult About() 
    { 
     return View((User as ClaimsPrincipal).Claims); 
    } 
} 

फिर ResourceAuthorize विशेषता से सजाया गया है की तरह परिभाषित करते हैं, जब मैं पहली बार इस विधि तक पहुंचने का प्रयास करता हूं, तो मुझे डिफ़ॉल्ट लॉगिन पेज पर रीडायरेक्ट कर दिया जाएगा।

क्या मैं फिर भी समझ में नहीं आता, यही वजह है कि जब मैं उपयोगकर्ता मैं आवेदन के लिए परिभाषित किया है के साथ प्रवेश (नीचे देखें),

public class Users 
{ 
    public static List<InMemoryUser> Get() 
    { 
     return new List<InMemoryUser> 
     { 
      new InMemoryUser 
      { 
       Username = "bob", 
       Password = "secret", 
       Subject = "1", 

       Claims = new[] 
       { 
        new Claim(Constants.ClaimTypes.GivenName, "Bob"), 
        new Claim(Constants.ClaimTypes.FamilyName, "Smith"), 
        new Claim(Constants.ClaimTypes.Role, "Geek"), 
        new Claim(Constants.ClaimTypes.Role, "LevelOneSubscriber") 
       } 
      } 
     }; 
    } 
} 

मैं एक 403 त्रुटि मिलती है, बियरर त्रुटि = "insufficient_scope "।

क्या कोई यह समझा सकता है कि मैं क्या गलत कर रहा हूं?

कार्रवाई विधि एक ही त्रुटि लौटाएगा उपयोग करने के लिए किसी भी बाद के प्रयास। ऐसा लगता है कि मैंने जिस उपयोगकर्ता को परिभाषित किया है, उसके पास सही तरीके से इस विधि तक पहुंचने में सक्षम होने का दावा है। हालांकि, दावों की जांच केवल एक बार होती है, जब मैं पहली बार इस विधि तक पहुंचने का प्रयास करता हूं। लॉगिन करने के बाद मुझे एक कुकी मिलती है, और दावों की जांच विधि के उपयोग के बाद के प्रयासों के दौरान नहीं की जाती है।

मैं थोड़ा खो दिया है, और इस ऊपर समाशोधन में कुछ मदद की सराहना करेंगे हूँ।

अग्रिम धन्यवाद।

संपादित करें: यहाँ scoles और ग्राहक वर्गों

public static class Scopes 
{ 
    public static IEnumerable<Scope> Get() 
    { 
     var scopes = new List<Scope> 
     { 
      new Scope 
      { 
       Enabled = true, 
       Name = "roles", 
       Type = ScopeType.Identity, 
       Claims = new List<ScopeClaim> 
       { 
        new ScopeClaim("role") 
       } 
      }, 
      new Scope 
      { 
       Enabled = true, 
       Name = "baseballStatsApi", 
       Description = "Access to baseball stats API", 
       Type = ScopeType.Resource, 
       Claims = new List<ScopeClaim> 
       { 
        new ScopeClaim("role") 
       } 
      } 
     }; 

     scopes.AddRange(StandardScopes.All); 

     return scopes; 
    } 
} 

और

public static class Clients 
{ 
    public static IEnumerable<Client> Get() 
    { 
     return new[] 
     { 
      new Client 
      { 
       Enabled = true, 
       ClientName = "Baseball Stats Emporium", 
       ClientId = "baseballStats", 
       Flow = Flows.Implicit,      

       RedirectUris = new List<string> 
       { 
        "https://localhost:44300/" 
       } 
      }, 
      new Client 
      { 
       Enabled = true, 
       ClientName = "Baseball Stats API Client", 
       ClientId = "baseballStats_Api", 
       ClientSecrets = new List<ClientSecret> 
       { 
        new ClientSecret("secret".Sha256()) 
       }, 
       Flow = Flows.ClientCredentials 
      } 
     }; 
    } 
} 

मैं भी जो मैं निर्धारित करने के लिए जब दावों की जांच किया जाता है का उपयोग कस्टम फ़िल्टर विशेषता बनाया है ग्राहक वर्ग के हैं ।

public class CustomFilterAttribute : ResourceAuthorizeAttribute 
{ 
    public CustomFilterAttribute(string action, params string[] resources) : base(action, resources) 
    { 
    } 

    protected override bool CheckAccess(HttpContextBase httpContext, string action, params string[] resources) 
    { 
     return base.CheckAccess(httpContext, action, resources); 
    } 
} 

ब्रेकपॉइंट केवल यूआरएल के प्रारंभिक अनुरोध पर ही मारा जाता है।बाद के अनुरोधों पर, फ़िल्टर विशेषता ब्रेकपॉइंट हिट नहीं होता है, और इस प्रकार कोई जांच नहीं होती है। यह मेरे लिए आश्चर्य की बात है क्योंकि मुझे लगता है कि जब भी यूआरएल अनुरोध किया जाता है तो जांच की जानी चाहिए।

+2

आप सवाल का scopes.cs और clients.cs जोड़ सकते हैं? Insufficiet_scope त्रुटि का अर्थ है "अनुरोध टोकन द्वारा प्रदान किए गए मुकाबले के मुकाबले उच्च विशेषाधिकारों की आवश्यकता है।" – rawel

+1

हाय, मैंने आपके द्वारा अनुरोधित कक्षाओं को जोड़ा। शायद दायरा का प्रकार गलत है? – Locust5304

उत्तर

3

आप में एपीआई के लिए आवश्यक लॉग जब उपयोगकर्ता स्कोप अनुरोध करना होगा। Scope = "openid profile roles baseballStatsApi"

   Authority = "https://localhost:44301/identity", 

       ClientId = "baseballStats", 
       Scope = "openid profile roles baseballStatsApi", 
       ResponseType = "id_token token", 
       RedirectUri = "https://localhost:44300/", 

       SignInAsAuthenticationType = "Cookies", 
       UseTokenLifetime = false, 
+0

हाय, आपके उत्तर के लिए धन्यवाद। मैंने वास्तव में दायरे और ग्राहक की प्रतिलिपि बनाने में गलती की। मैंने अभी पोस्ट अपडेट किया है। उसके लिए माफ़ करना। – Locust5304

+0

बेसबॉलस्टैटएपीआई स्कोप आपके एपीआई द्वारा आवश्यक है, लेकिन आपका एप्लिकेशन() उस दायरे का अनुरोध नहीं करता है, क्या आप कृपया स्कोप = "ओपनिड प्रोफाइल रोल बेसबॉलस्टैटएपीआई" संशोधित करने की जांच कर सकते हैं, – rawel

+0

अभी भी कोई भाग्य नहीं है। मैंने आपके द्वारा सुझाए गए परिवर्तन किए हैं और कोड की स्थिति को दर्शाने के लिए मूल पोस्ट को अपडेट किया है। मुझे अब भी वही त्रुटि मिलती है। – Locust5304