gpt4 book ai didi

c# - 使用 Asp.Net MVC 应用程序设置 IdentityServer

转载 作者:太空狗 更新时间:2023-10-29 20:33:34 26 4
gpt4 key购买 nike

对于提出这个问题,我提前表示歉意,因为我几乎不了解一般的安全性,尤其是 IdentityServer。

我正在尝试设置 IdentityServer 来管理 Asp.Net MVC 应用程序的安全性。

我正在按照他们网站上的教程进行操作: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();
}
}
}

例如,如果我定义一个用 ResourceAuthorize 属性修饰的 Controller 方法,就像这样

 public class HomeController : Controller
{

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

然后,当我第一次尝试访问此方法时,我将被重定向到默认登录页面。

但是我不明白的是,为什么当我使用我为应用程序定义的用户登录时(见下文),

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 错误,Bearer error="insufficient_scope"。

任何人都可以解释我做错了什么吗?

任何后续访问操作方法的尝试都将返回相同的错误。在我看来,我定义的用户拥有能够访问此方法的正确声明。但是,当我第一次尝试访问此方法时,声明检查只发生一次。登录后我得到一个 cookie,并且在随后尝试访问该方法时不会进行声明检查。

我有点迷路了,如果能帮我解决这个问题,我将不胜感激。

提前致谢。

编辑:这里是 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);
}
}

断点仅在对 url 的初始请求时命中。在后续请求中,不会命中过滤器属性断点,因此不会进行检查。这让我感到惊讶,因为我认为每次请求 url 时都必须进行检查。

最佳答案

需要在用户登录时请求api需要的scope。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,

关于c# - 使用 Asp.Net MVC 应用程序设置 IdentityServer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30770951/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com