通过删除配置文件服务中的声明来减少 IdentityServer4 access_token 长度

问题描述 投票:0回答:1

我正在开发 IdentityServer4 应用程序。由于添加到 context.IssuedClaims 的声明值,生成的 Access_token 长度变得太长。我尝试删除称为“实体”的声明类型,它有助于减少 access_token 长度。但它也从 ClaimsPrincipal 中删除了索赔。有没有办法可以将此声明添加回我的 ClaimsPrincipal 中,以便我可以从所有客户端应用程序访问它?目前,我每次都会调用一个单独的 API 来取回索赔。下面是我的 ProfileService 中的代码,我在其中过滤声明。

public async Task GetProfileDataAsync(IdentityServer4.Models.ProfileDataRequestContext context)
{
    var user = await _userManager.GetUserAsync(context.Subject);
    var principal = await _claimsFactory.CreateAsync(user);            
    //Retrieve all the claims associated with the user
    var claims = from claimsdata in principal.Claims select new System.Security.Claims.Claim(claimsdata.Type, claimsdata.Value);
    //Exclude claim type "entity" since its huge in numbers and causing access_token size to grow
    var claimsWithoutEntity = claims.Where(x => x.Type != "entity");
    context.IssuedClaims.AddRange(claimsWithoutEntity);
    var roleClaims = _roleService.GetRoleClaims(user);
    context.IssuedClaims.AddRange(roleClaims);
}
asp.net asp.net-mvc asp.net-core identityserver4
1个回答
1
投票

在不修改访问令牌的情况下减少 cookie 大小的另一种替代方法是创建 SessionStore,您可以在此处使用 SessionStore 参数设置它:

}).AddCookie(options =>
{
   ...     
   options.SessionStore = new MySessionStore();

})

SessionStore 有什么作用?

看这张照片,取自我的一堂培训课:

这是内存存储示例

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Serilog;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace SessionStore
{
    /// <summary>
    /// MySessionStore
    /// 
    /// Custom session store, to hold the tokens in memory instead of storing them inside the Cookie.
    /// 
    /// This provides an abstract storage mechanic to preserve identity information on the server while 
    /// only sending a simple identifier key to the client. This is most commonly used to mitigate issues 
    /// with serializing large identities into cookies.
    /// 
    /// TODO: 
    /// - Needs logic to remove older items, otherwise we might run out of memory here.
    /// - Use the MemoryCache instead of a dictionary?
    /// 
    /// Written by Tore Nestenius to be used in the IdentityServer in production training class.
    /// https://www.tn-data.se
    /// 
    /// </summary>
    internal class MySessionStore : ITicketStore
    {
        private readonly Serilog.ILogger _logger;

        private readonly ConcurrentDictionary<string, AuthenticationTicket> mytickets = new();

        public MySessionStore()
        {
            _logger = Log.Logger;
        }

        /// <summary>
        /// Remove the identity associated with the given key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task RemoveAsync(string key)
        {
            _logger.Debug("MySessionStore.RemoveAsync Key=" + key);

            if (mytickets.ContainsKey(key))
            {
                mytickets.TryRemove(key, out _);
            }

            return Task.FromResult(0);
        }

        /// <summary>
        /// Tells the store that the given identity should be updated.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="ticket"></param>
        /// <returns></returns>
        public Task RenewAsync(string key, AuthenticationTicket ticket)
        {
            _logger.Debug("MySessionStore.RenewAsync Key=" + key + ", ticket = " + ticket.AuthenticationScheme);

            mytickets[key] = ticket;

            return Task.FromResult(false);
        }


        /// <summary>
        /// Retrieves an identity from the store for the given key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<AuthenticationTicket> RetrieveAsync(string key)
        {
            _logger.Error("MySessionStore.RetrieveAsync Key=" + key);

            if (mytickets.ContainsKey(key))
            {
                var ticket = mytickets[key];
                return Task.FromResult(ticket);
            }
            else
            {
                return Task.FromResult((AuthenticationTicket)null!);
            }
        }


        /// <summary>
        /// Store the identity ticket and return the associated key.
        /// </summary>
        /// <param name="ticket"></param>
        /// <returns></returns>
        public Task<string> StoreAsync(AuthenticationTicket ticket)
        {
            //Only add one at the time to avoid race conditions
            lock(this)
            {

                //Make sure the key is does not already exist in the dictionary
                bool result = false;
                string key;
                do
                {
                    key = Guid.NewGuid().ToString();
                    result = mytickets.TryAdd(key, ticket);
                } while (result == false);

                string username = ticket?.Principal?.Identity?.Name ?? "Unknown";
                _logger.Debug("MySessionStore.StoreAsync ticket=" + username + ", key=" + key);

                return Task.FromResult(key);
            }
  
        }
    }
}

我确实写了一篇博文,更多地讨论了会话存储的目的以及它如何提高安全性: 通过减少 Cookie 来提高 ASP.NET Core 安全性

© www.soinside.com 2019 - 2024. All rights reserved.