gpt4 book ai didi

identityserver4 - 使用 IdentityServer4 对 Web API 进行基于角色的授权

转载 作者:行者123 更新时间:2023-12-04 08:31:42 27 4
gpt4 key购买 nike

我将 IdentityServer4 (v2.2.1) 与 .Net Core 2.0 和 Asp.Net Core Identity 一起使用。
我的解决方案中有三个项目。

  • 身份服务器
  • 网络接口(interface)
  • MVC Web 应用程序

  • 我正在尝试在我的 Web API 上实现基于角色的授权,以便任何客户端都将访问 token 传递给 Web API 以访问资源。

    目前我可以在 MVC 应用程序 Controller 上实现基于角色的授权,但我不能为 WEB API Controller 传递/配置相同的授权。

    以下是身份服务器文件:
    配置文件
    public static IEnumerable<ApiResource> GetApiResources()
    {
    return new List<ApiResource>
    {
    //SCOPE - Resource to be protected by IDS
    new ApiResource("TCSAPI", "TCS API")
    {
    UserClaims = { "role" }
    }
    };
    }


    public static IEnumerable<Client> GetClients()
    {
    return new List<Client>
    {
    new Client
    {
    ClientId = "TCSIdentity",
    ClientName = "TCS Mvc Client Application .",
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    RequireConsent = false,
    ClientSecrets =
    {
    new Secret("secret".Sha256())
    },

    RedirectUris = { "http://localhost:5002/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

    AlwaysSendClientClaims= true,
    AlwaysIncludeUserClaimsInIdToken = true,

    AllowedScopes =
    {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Email,
    IdentityServerConstants.StandardScopes.Profile,
    IdentityServerConstants.StandardScopes.OfflineAccess,
    "TCSAPI",
    "office",
    "role",
    },
    AllowOfflineAccess = true
    }
    };
    }

    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
    return new IdentityResource[]
    {
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResources.Email(),
    new IdentityResource
    {
    Name = "role",
    DisplayName="User Role",
    Description="The application can see your role.",
    UserClaims = new[]{JwtClaimTypes.Role,ClaimTypes.Role},
    ShowInDiscoveryDocument = true,
    Required=true,
    Emphasize = true
    }
    };
    }

    启动.cs
     public void ConfigureServices(IServiceCollection services)
    {
    services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryPersistedGrants()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddAspNetIdentity<ApplicationUser>();
    }

    MVC WEB APP(角色基础授权适用于 MVC WEB APP):

    RoleClaimAction.cs
    使用此文件将角色添加到身份。
    internal class RoleClaimAction : ClaimAction
    {
    public RoleClaimAction()
    : base("role", ClaimValueTypes.String)
    {
    }

    public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
    {
    var tokens = userData.SelectTokens("role");
    IEnumerable<string> roles;

    foreach (var token in tokens)
    {
    if (token is JArray)
    {
    var jarray = token as JArray;
    roles = jarray.Values<string>();
    }
    else
    roles = new string[] { token.Value<string>() };

    foreach (var role in roles)
    {
    Claim claim = new Claim("role", role, ValueType, issuer);
    if (!identity.HasClaim(c => c.Subject == claim.Subject
    && c.Value == claim.Value))
    {
    identity.AddClaim(claim);
    }
    }
    }
    }
    }

    MVC WEB APP/Startup.cs
     public void ConfigureServices(IServiceCollection services)
    {
    services.AddMvc();

    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    services.AddCors();
    services.AddAuthentication(options =>
    {
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
    options.SignInScheme = "Cookies";
    options.Authority = "http://localhost:5000";
    options.RequireHttpsMetadata = false;

    options.ClientId = "TCSIdentity";

    //HYBRID FLOW
    options.ClientSecret = "secret";

    options.ClaimActions.Add(new RoleClaimAction()); // <--

    options.ResponseType = "code id_token token";
    options.GetClaimsFromUserInfoEndpoint = true;
    options.Scope.Add("TCSAPI");
    options.Scope.Add("offline_access");
    //END HYBRID FLOW
    options.SaveTokens = true;
    options.Scope.Add("role");

    options.TokenValidationParameters.NameClaimType = "name";
    options.TokenValidationParameters.RoleClaimType = "role";
    });

    }

    MVC WEB APP/HomeController.cs
    此操作方法适用于角色基础授权,但是当我尝试将 token 传递给 Web Api 以使用角色基础授权访问任何内容时,它无法授权。例如
    var content = await client.GetStringAsync(" http://localhost:5001/user");
    [Authorize(Roles = "User")]
    [Route("user")]
    public async Task<IActionResult> UserAccess()
    {

    var tokenClient = new TokenClient("http://localhost:5000/connect/token", "RoleApi", "secret");
    var tokenResponse = await tokenClient.RequestClientCredentialsAsync("TCSAPI");

    var client = new HttpClient();
    client.SetBearerToken(tokenResponse.AccessToken);
    var content = await client.GetStringAsync("http://localhost:5001/user");

    ViewBag.Json = JArray.Parse(content).ToString();
    return View("json");
    }
    [Authorize(Roles = "Admin")]
    [Route("admin")]
    public async Task<IActionResult> AdminAccess()
    {
    var accessToken = await HttpContext.GetTokenAsync("id_token");

    var client = new HttpClient();
    client.SetBearerToken(accessToken);
    var content = await client.GetStringAsync("http://localhost:5001/admin");
    ViewBag.Json = JArray.Parse(content).ToString();
    return View("json");
    }

    WEBAPI/启动.cs
     public void ConfigureServices(IServiceCollection services)
    {
    services.AddMvcCore()
    .AddAuthorization()
    .AddJsonFormatters();
    services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
    options.Authority = "http://localhost:5000";
    options.RequireHttpsMetadata = false;
    options.ApiName = "TCSAPI";
    });

    services.AddCors(options =>
    {
    options.AddPolicy("default", policy =>
    {
    policy.WithOrigins("http://localhost:5002")
    .AllowAnyHeader()
    .AllowAnyMethod();
    });
    });
    }

    WEB API/TestController.cs
    [Route("admin")]
    [Authorize(Roles = "Admin")]
    public IActionResult AdminAccess()
    {
    return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
    [Route("user")]
    [Authorize(Roles = "User")]
    public IActionResult UserAccess()
    {
    return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
    [AllowAnonymous]
    [Route("public")]
    public IActionResult PublicAccess()
    {
    return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }

    最佳答案

    您的代码不完全是基于策略的授权。您的看起来像 .NET Framework 基于角色的授权。

    对于Policy Based Authorization ,你需要做以下事情:

    1. Startup.cs在您的 Web API 项目中,您需要添加以下内容:

    // more code
    .AddMvcCore()
    .AddAuthorization(options =>
    {
    options.AddPolicy("Policy1",
    policy => policy.Requirements.Add(new Policy1Requirement()));
    options.AddPolicy("Policy2",
    policy => policy.Requirements.Add(new Policy2Requirement()));
    .
    .
    .
    .
    })
    // more code

    2. 然后你需要为每个 Policy(X)Requirement 设置一个类:
    public class Policy1Requirement : AuthorizationHandler<Policy1Requirement>, IAuthorizationRequirement
    {
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminUserRequirement requirement)
    {
    if (!context.User.HasClaim(c => c.Type == "role" && c.Value == "<YOUR_ROLE_FOR_THIS_POLICY>"))
    {
    context.Fail();
    }
    else
    {
    context.Succeed(requirement);
    }
    return Task.FromResult(0);
    }
    }

    3. 最后,在您应用策略的地方,您需要:
    [Authorize(Policy = "Policy1")]
    public class MyController : Controller
    {
    .
    .
    }

    祝你好运!

    PS:

    姓名 Policy(X)Policy(X)Requirement只是为了澄清。你可以使用任何你想要的名字,只要你实现了正确的接口(interface) IAuthorizationRequirement , 并继承类 AuthorizationHandler

    关于identityserver4 - 使用 IdentityServer4 对 Web API 进行基于角色的授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50266114/

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