【个人博客搭建】(20)获取操作用户信息(IHttpContextAccessor)

IHttpContextAccessor在ASP.NET Core中扮演着至关重要的角色。它为开发者提供了一种方便的方式来访问和操作HttpContext对象,从而允许在整个应用程序中轻松地管理和使用HTTP请求和响应的相关信息。下面将深入探讨IHttpContextAccessor的作用、使用方法以及如何通过它来优化Web API的开发流程:

  1. 访问HttpContext
    • 中间件和应用框架中的使用:HttpContext封装了有关个别HTTP请求和响应的所有信息,当收到HTTP请求时,HttpContext实例会进行初始化。这个实例可以通过中间件和应用框架(如Web API控制器、Razor Pages等)访问。
    • 读取请求头和响应头:通过HttpRequest和HttpResponse的属性,可以访问和使用HTTP请求和响应的头部信息,这对于处理HTTP通信中的重要元数据至关重要。
    • 读取请求正文:HTTP请求可以包含请求正文,例如HTML窗体的内容、UTF-8 JSON有效负载或文件。IHttpContextAccessor允许读取这些数据,这对于处理客户端发送的数据非常重要。
  2. 中间件中的应用
    • 启用请求正文缓冲:在某些情况下,需要多次读取请求正文。IHttpContextAccessor提供了扩展方法来缓冲HTTP请求正文,并支持大型请求正文的处理。
    • 处理OPTIONS预检请求:在处理跨域请求时,正确处理OPTIONS预检请求是必要的。通过IHttpContextAccessor,可以设置允许的HTTP方法和头部字段,以确保CORS策略的正确实施。
  3. 依赖注入
    • 注册IHttpContextAccessor服务:在Startup类的ConfigureServices方法中,需要注册IHttpContextAccessor为一个单例服务,这样它就可以在应用程序的其他部分通过依赖注入来使用。
    • 使用中间件配置静态HttpContext:通过扩展方法,可以在应用的中间件管道中配置IHttpContextAccessor,以便在整个应用程序中使用HttpContext.Current。
  4. 安全性考虑
    • 避免线程安全问题:HttpContext不是线程安全的,因此在并行任务中直接引用HttpContext数据可能会导致异常。应传递所需的数据而不是HttpContext本身,以避免不安全代码。
    • 管理用户身份:IHttpContextAccessor可以用于获取或设置请求的用户,这在处理身份验证和授权时非常有用。
  5. 功能接口集合
    • 访问请求功能:HttpContext提供对当前请求的功能接口集合的访问。这些功能集合是可变的,可以通过中间件来修改,以添加对其他功能的支持。
    • 使用高级API:通过BodyReader属性,可以直接访问请求正文,这种高级的、高性能的方法适合那些需要高效处理请求数据的应用场景。

此外,在使用IHttpContextAccessor时,还应注意以下几点:

  • 响应写入注意事项:在写入响应正文时,必须注意响应是否已启动,因为一旦响应启动,标头将变为只读。
  • 处理取消令牌:在执行长时间运行的任务时,应使用RequestAborted取消令牌,以便在请求中止时能够及时停止任务。
  • 异步操作中的应用:在异步操作中,应将IHttpContextAccessor作为参数传递,以确保在等待异步操作完成时不会引用到已经结束的请求上下文。

综上所述,IHttpContextAccessor在ASP. NET Core中提供了一种灵活且强大的机制,用于访问和操作HttpContext实例。它不仅简化了对HTTP请求和响应信息的访问,而且还支持中间件和应用框架中的高级功能。通过合理利用IHttpContextAccessor,开发者可以更加高效地构建和管理Web API,同时也要注意其安全性和性能方面的考量。

1、创建IHttpContextUser接口

 public interface IHttpContextUser
 {
     string Name { get; }
     int JwtID { get; }
     bool IsAuthenticated();
     IEnumerable<Claim> GetClaimsIdentity();
     List<string> GetClaimValueByType(string ClaimType);

     string GetToken();
     List<string> GetUserInfoFromToken(string ClaimType);


     
     #region 拓展(具体使用的)


     int userId { get; }
     string userName { get; }
     string userAccount { get; }
     

     #endregion
 }

 2、实现接口,创建类AspNetUser

public class AspNetUser : IHttpContextUser
{
    private readonly IHttpContextAccessor _accessor;

    public AspNetUser(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    public string Name => _accessor.HttpContext.User.Identity.Name;

    /// <summary>
    /// 是jwt的唯一身份标识,主要用来作为一次性的token,从而回避重放攻击,可以用uuid进行设置
    /// </summary>
    public int JwtID => GetClaimValueByType("jti").FirstOrDefault().ObjToInt();

    /// <summary>
    /// 是否通过验证
    /// </summary>
    /// <returns></returns>
    public bool IsAuthenticated()
    {
        return _accessor.HttpContext.User.Identity.IsAuthenticated;
    }

    /// <summary>
    /// 获取token
    /// </summary>
    /// <returns></returns>
    public string GetToken()
    {
        return _accessor.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "");
    }

    public List<string> GetUserInfoFromToken(string ClaimType)
    {

        var jwtHandler = new JwtSecurityTokenHandler();
        if (!string.IsNullOrEmpty(GetToken()))
        {
            JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(GetToken());

            return (from item in jwtToken.Claims
                    where item.Type == ClaimType
                    select item.Value).ToList();
        }
        else
        {
            return new List<string>() { };
        }
    }

    public IEnumerable<Claim> GetClaimsIdentity()
    {
        return _accessor.HttpContext.User.Claims;
    }

    public List<string> GetClaimValueByType(string ClaimType)
    {

        return (from item in GetClaimsIdentity()
                where item.Type == ClaimType
                select item.Value).ToList();

    }

    #region MyRegion 拓展

    public int userId => GetClaimValueByType("userId").FirstOrDefault().ObjToInt();//账号id
    public string userName => GetClaimValueByType("userName").FirstOrDefault();//姓名
    public string userAccount => GetClaimValueByType("userAccount").FirstOrDefault();//登录账号名

    #endregion

}

3、注入服务:


#region HttpContext 相关服务

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddScoped<IHttpContextUser, AspNetUser>();

#endregion

4、测试:

        4.1、在user的接口那边加了个Test的方法,然后构造函数内添加IHttpContextUser 对象。获取

        private readonly Repository<SysUser> _usersRep;
        private readonly IHttpContextUser _user;

        public SysUserService(Repository<SysUser> usersRep, IHttpContextUser user)
        {
            _usersRep = usersRep;
            _user = user;
        }

        public async Task<ApiResult> Test()
        {
            var userid = _user.userId;
            var username = _user.userName;
            var result = "userid:" + userid + ";username:" + username + ";" ;
            return ApiResultHelper.Success(result);
        }

        4.2、使用swagger或ApiPost调用:(记得携带Token)

        这样就可以带出存入Jwt中的相关信息了。

        如果需要其他信息,在生成Token时存入即可。

       可查看文章:【个人博客搭建】(10)添加JWT-CSDN博客

5、其他

        ......

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值