AbpSession 扩展

本文介绍了如何在基于ABP框架的项目中扩展IAbpSession接口,添加自定义的用户属性,如UsercId、PermitNo等。首先创建了IAbpSessionExtension接口,然后实现AbpSessionExtension类,从ClaimsAbpSession继承并添加新方法来获取扩展的用户属性。在用户登录时,将这些属性作为 Claims 添加到身份中,以便后续可以通过扩展的AbpSession访问。最后展示了如何在代码中使用这些扩展的会话属性。

1、在*.Core 下找到Extensions文件夹添加AbpSessionExtension.cs类和IAbpSessionExtension.cs类

2、IAbpSessionExtension继承IAbpSession

using Abp.Runtime.Session;
using System;
using System.Collections.Generic;
using System.Text;

namespace MyProject.Extensions
{
    public interface IAbpSessionExtension : IAbpSession
    {
        
        public string GetUsercId { get; }
        public string GetPermitNo { get; }
        public string GetUserdeptId { get; }
        public string GetWxOpenId { get; }

    }
}

3、AbpSessionExtension继承ClaimsAbpSession和IAbpSessionExtension


using Abp.Configuration.Startup;
using Abp.MultiTenancy;
using Abp.Runtime;
using Abp.Runtime.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;

namespace MyProject.Extensions
{
    /// <summary>
    /// 对AbpSession的扩展
    /// </summary>
    public class AbpSessionExtension : ClaimsAbpSession, IAbpSessionExtension
    {
        public AbpSessionExtension(IPrincipalAccessor principalAccessor,
            IMultiTenancyConfig multiTenancy,
            ITenantResolver tenantResolver,
            IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider) :
            base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
        {
        }
        
       
        private string GetClaimValue(string claimType)
        {
            var claimsPrincipal = this.PrincipalAccessor.Principal;

            var claim = claimsPrincipal?.Claims.FirstOrDefault(c => c.Type == claimType);
            if (string.IsNullOrEmpty(claim?.Value))
                return null;

            return claim.Value;
        }
        public string GetUsercId => GetClaimValue("UsercId");
        public string GetPermitNo => GetClaimValue("PermitNo");
        public string GetUserdeptId => GetClaimValue("UserdeptId");
        public string GetWxOpenId => GetClaimValue("WxOpenId");
    }
}

4、添加Session

loginResult.Identity.AddClaim(new Claim("UserdeptId", loginResult.User.deptId.ToString()));
loginResult.Identity.AddClaim(new Claim("UsercId", loginResult.User.cId.ToString()));

 

 public async Task<AuthenticateResultModel> Authenticate([FromBody] AuthenticateModel model)
        {
            var loginResult = await GetLoginResultAsync(
                model.UserNameOrEmailAddress,
                model.Password,
                GetTenancyNameOrNull()
            );
            //AbpSession.UsercId = loginResult.User.cId;
            //AbpSession.UserdeptId = loginResult.User.deptId;
            loginResult.Identity.AddClaim(new Claim("UserdeptId", loginResult.User.deptId.ToString()));
            loginResult.Identity.AddClaim(new Claim("UsercId", loginResult.User.cId.ToString()));

            if (AbpSession.WxOpenId != "")
            {
                var user = await _userManager.GetUserByIdAsync(loginResult.User.Id);
                user.wxopenid = AbpSession.WxOpenId;
                await _userManager.UpdateAsync(user);
            }
            var accessToken = CreateAccessToken(CreateJwtClaims(loginResult.Identity));
            return new AuthenticateResultModel
            {
                AccessToken = accessToken,
                EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
                ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds,
                UserId = loginResult.User.Id
            };
        }

5、调用扩展的Session

AbpSession.UserdeptId

using Abp.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Senparc.Weixin.TenPay.V3; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using TaiHeTun.Mall.EntityFrameworkCore.Repositories; using TaiHeTun.Mall.Helpers; using TaiHeTun.Mall.HuoDong; using TaiHeTun.Mall.Models; using TaiHeTun.Mall.Pay; using TaiHeTun.Mall.Pay.Dto; using TaiHeTun.Mall.Shop; using TaiHeTun.Mall.Shop.Dto; using TaiHeTun.Mall.Users; namespace TaiHeTun.Mall.Mall { /// <summary> /// 支付相关 /// </summary> [ApiExplorerSettings(GroupName = "Mall")] [Route("api/Mall/[controller]/[action]")] [AbpAuthorize] public class PayController : MallAppServiceBase { private readonly IPreCreateOrderAppService _preCreateOrderAppService; private readonly ISendWechatMessageAppService _sendWechatMessageAppService; private readonly IStoreProcedureRepository _storeProcedureRepository; private readonly IOrderAppService _orderAppService; private readonly IGroupBuyingEventAppService _groupBuyingEventAppService; private readonly IWxPayAppService _wxPay; private readonly ICustomFunctionAppService _customFunctionAppService; public PayController(IPreCreateOrderAppService preCreateOrderAppService, IOrderAppService orderAppService, ISendWechatMessageAppService sendWechatMessageAppService, ICustomFunctionAppService customFunctionAppService, IStoreProcedureRepository storeProcedureRepository, IWxPayAppService wxPay, IGroupBuyingEventAppService groupBuyingEventAppService) { _preCreateOrderAppService = preCreateOrderAppService; _customFunctionAppService = customFunctionAppService; _orderAppService = orderAppService; _sendWechatMessageAppService = sendWechatMessageAppService; _storeProcedureRepository = storeProcedureRepository; _wxPay = wxPay; _groupBuyingEventAppService = groupBuyingEventAppService; } /// <summary> /// 根据商品创建并返回预支付id /// 如果是拼团商品需要在这里判断拼团人数是否已满 /// </summary> /// <param name="input"></param> /// <returns></returns> [HttpPost] public ResultDtos<Guid, Boolean> GetPreOrderId([FromBody] List<PreCreateOrderCreateDto> input) { try { var CheckCreateOrderState = false; Guid id = Guid.NewGuid(); ; if (input.Count == 0) { return new ResultDtos<Guid, Boolean> { Code = 1, Mes = "参数不能为空" }; } else { if (input[0].PtId != null && input[0].PtId != Guid.Empty) { //如果是拼团订单在这里返回用户是否需要新开团 CheckCreateOrderState = _groupBuyingEventAppService.CheckCreateOrder(input[0].PtId.Value); } if (_preCreateOrderAppService.CheckData(input) == 0) { foreach (var item in input) { var entity = ObjectMapper.Map<PreCreateOrderInputDto>(item); entity.PreId = id; entity.UserId = (int)AbpSession.UserId; _preCreateOrderAppService.Insert(entity); } return new ResultDtos<Guid, Boolean> { Code = 0, Mes = "创建成功", Data = id, OhtherData = CheckCreateOrderState }; } else { return new ResultDtos<Guid, Boolean> { Code = 1, Mes = "商品已过期" }; } } } catch (Exception ex) { return new ResultDtos<Guid, Boolean> { Code = 1, Mes = "账号异常" }; } } /// <summary> /// 购买过指定商品的用户才可以享受优惠 /// </summary> /// <param name="ProductName">指定商品名称</param> /// <returns></returns> [HttpGet] public ResultDto CheckOldUser(string ProductName) { if (AbpSession.UserId.Value == 2323) { return new ResultDto { Code = 0, Mes = "" }; } string ids = "4656,2479,1279,5631,5623,2841,5413,5319,4974,5050,4999,4750,3670,4738,4744,4640,4501,228,85,238,272,311,322,335,542,954,1182,1285,1294,1553,1665,1897,1984,1987,2024,2045,2078,2121,2123,2136,2144,2198,2226,2230,2235,2237,2238,2266,2384,2388,2394,2456,2462,2477,2520,2606,2718,2770,2778,2780,2786,2803,2809,2810,2813,2825,2829,2833,2840,2881,2919,2933,2934,2989,2995,3025,3038,3060,3156,3161,3164,3191,3200,3211,3214,3223,3238,3240,3283,3284,3299,3302,3306,3314,3423,3436,3469,3486,3521,3532,3569,3663,3676,3929,3970,3998"; List<int> us = new List<int>(); foreach (var item in ids.Split(',')) { us.Add(int.Parse(item)); } if (us.Count(g => g == AbpSession.UserId) > 0) { return new ResultDto { Code = 0, Mes = "" }; } var result = _customFunctionAppService.CheckOldUser(ProductName, AbpSession.UserId.Value); if (result.success) { return new ResultDto { Code = 0, Mes = "" }; } else { return new ResultDto { Code = 1, Mes = result.message }; } } /// <summary> /// 根据预支付id查询返回创建订单页面数据 /// </summary> /// <param name="id">预支付id</param> /// <param name="AddressId">用户选择的收货地址id,可不传(按默认收货执行)</param> /// <returns></returns> [HttpPost] public ResultDto<CreateOrderDto> GetCreateOrderDetail(Guid id, Guid? AddressId) { var dfd = _preCreateOrderAppService.GetCreateOrderDetail(id, (int)AbpSession.UserId, AddressId); return new ResultDto<CreateOrderDto> { Code = 0, Data = dfd, Mes = "查询成功" }; } /// <summary> /// 提提交订单并返回订单编号【支持多店铺】 /// </summary> /// <param name="input"></param> [HttpPost] public ResultDto<List<Guid?>> CreateOrder([FromBody] CreateShopOrderDto input) { var dfd = _preCreateOrderAppService.CreateOrder(input, (int)AbpSession.UserId); if (dfd.State == 0) { return new ResultDto<List<Guid?>> { Code = 1, Data = null, Mes = "创建失败" }; } else if (dfd.State == 2) { return new ResultDto<List<Guid?>> { Code = 1, Data = null, Mes = "库存不足" }; } else if (dfd.State == 3) { return new ResultDto<List<Guid?>> { Code = 1, Data = null, Mes = "创建失败存在失效商品" }; } else if (dfd.State == 4) { return new ResultDto<List<Guid?>> { Code = 1, Data = null, Mes = "您有商品超过限购数量限制" }; } else { return new ResultDto<List<Guid?>> { Code = 0, Data = dfd.Orderids, Mes = "创建成功" }; } } /// <summary> /// 提提交订单并返回订单编号【支持多店铺】 /// </summary> /// <param name="input"></param> [HttpPost] public ResultDto<List<Guid?>> CreateGroupOrder([FromBody] CreateShopOrderDto input) { var dfd = _preCreateOrderAppService.CreateGroupOrder(input, (int)AbpSession.UserId); if (dfd.State == 0) { return new ResultDto<List<Guid?>> { Code = 1, Data = new List<Guid?> { }, Mes = "创建失败" }; } else if (dfd.State == 3) { return new ResultDto<List<Guid?>> { Code = 1, Data = new List<Guid?> { }, Mes = "创建失败存在失效商品" }; } else if (dfd.State == 5) { return new ResultDto<List<Guid?>> { Code = 1, Data = new List<Guid?> { }, Mes = "拼团活动已结束" }; } else if (dfd.State == 51) { return new ResultDto<List<Guid?>> { Code = 1, Data = new List<Guid?> { }, Mes = "存在未支付的订单" }; } else if (dfd.State == 52) { return new ResultDto<List<Guid?>> { Code = 1, Data = new List<Guid?> { }, Mes = "该活动仅限新用户参加" }; } else { return new ResultDto<List<Guid?>> { Code = 0, Data = dfd.Orderids, Mes = "成功" }; } } /// <summary> /// 根据订单id获取订单详情 /// </summary> /// <param name="Ids">多订单id逗号分割</param> /// <returns></returns> [HttpGet] public ResultDto<List<OrderListDto>> GetOrderDetail(string Ids) { List<Guid> Id = new List<Guid>(); List<OrderListDto> result = new List<OrderListDto>(); foreach (var item in Ids.Split(",")) { result.Add(_orderAppService.GetOneById(Guid.Parse(item))); } return new ResultDto<List<OrderListDto>> { Code = 0, Data = result, Mes = "查询成功" }; } /// <summary> /// 根据订单完成支付 /// 【2022年2月17日14:36:44】如果支付密码为paywx表示余额不足,充值成功后调用的支付这里不判断支付密码是否存在 /// </summary> [HttpPost] public ResultDto OrderPay([FromBody] PayDataDto input) { var result = _orderAppService.UserPayCheck(input.OrderId.Select(g => g.Id).ToList(), (int)AbpSession.UserId, input.PaymentPassword); if (result == 1) { return new ResultDto { Code = 1, Mes = "余额不足,请充值" }; } else if (result == 4) { return new ResultDto { Code = 2, Mes = "订单异常" }; } else { Hashtable ht = new Hashtable(); ht.Add("@order", ListToDataTable(input.OrderId)); ht.Add("@userid", AbpSession.UserId); var dfdd = _storeProcedureRepository.GetFromStoreProcedure("Pro_PayOrder", ht); int resultid = Convert.ToInt32(dfdd.Rows[0].Table.Rows[0]["id"]); if (resultid == 0) { return new ResultDto { Code = 1, Mes = "订单异常" }; } else if (resultid == 2) { return new ResultDto { Code = 1, Mes = "余额不足,请充值" }; } else { foreach (var item in input.OrderId) { _sendWechatMessageAppService.SendDeliveryRelease(item.Id); } //在此处增加推送通知 return new ResultDto { Code = 0, Mes = "支付成功" }; } } } public class PayDataDto { /// <summary> /// 支付订单 /// </summary> public List<GuidList> OrderId { get; set; } /// <summary> /// 支付密码 /// </summary> public string PaymentPassword { get; set; } } public class GuidList { /// <summary> /// 订单id /// </summary> public Guid Id { get; set; } } /// <summary> /// 订单确认收货 /// </summary> /// <param name="OrderId">订单id</param> /// <param name="PaymentPassword">支付密码</param> /// <returns></returns> [HttpPost] public ResultDto CompleteOrder(Guid OrderId, string PaymentPassword) { var pas = _orderAppService.GetOneById(OrderId); //(int)AbpSession.UserId); if (pas.Userid == (int)AbpSession.UserId) { Hashtable ht = new Hashtable(); ht.Add("@orderid", OrderId); var dfdd = _storeProcedureRepository.GetFromStoreProcedure("Pro_CompleteOrder", ht); int resultid = Convert.ToInt32(dfdd.Rows[0].Table.Rows[0]["id"]); if (resultid == 0) { return new ResultDto { Code = 1, Mes = "订单异常" }; } else { var order = _orderAppService.GetOneById(OrderId); return new ResultDto { Code = 0, Mes = "操作成功" }; } } else { return new ResultDto { Code = 1, Mes = "订单异常" }; } } /// <summary> /// 订单确认收货(定时器) /// </summary> /// <param name="OrderId">订单id</param> /// <param name="PaymentPassword">支付密码</param> /// <param name="UserId">用户id</param> /// <returns></returns> [HttpPost] [AbpAllowAnonymous] public ResultDto CompleteOrderForTimer(Guid OrderId, string PaymentPassword, int UserId) { var pas = _orderAppService.GetOneById(OrderId); //(int)AbpSession.UserId); if (pas.Userid == UserId) { Hashtable ht = new Hashtable(); ht.Add("@orderid", OrderId); var dfdd = _storeProcedureRepository.GetFromStoreProcedure("Pro_CompleteOrder", ht); int resultid = Convert.ToInt32(dfdd.Rows[0].Table.Rows[0]["id"]); if (resultid == 0) { return new ResultDto { Code = 1, Mes = "订单异常" }; } else { var order = _orderAppService.GetOneById(OrderId); return new ResultDto { Code = 0, Mes = "操作成功" }; } } else { return new ResultDto { Code = 1, Mes = "订单异常" }; } } [ApiExplorerSettings(GroupName = "Mall", IgnoreApi = true)] public static System.Data.DataTable ListToDataTable(IList list) { System.Data.DataTable result = new System.Data.DataTable(); if (list.Count > 0) { PropertyInfo[] propertys = list[0].GetType().GetProperties(); foreach (PropertyInfo pi in propertys) { //获取类型 Type colType = pi.PropertyType; //当类型为Nullable<>时 if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>))) { colType = colType.GetGenericArguments()[0]; } result.Columns.Add(pi.Name, colType); } for (int i = 0; i < list.Count; i++) { ArrayList tempList = new ArrayList(); foreach (PropertyInfo pi in propertys) { object obj = pi.GetValue(list[i], null); tempList.Add(obj); } object[] array = tempList.ToArray(); result.LoadDataRow(array, true); } } return result; } } } 这里面的就生效了
最新发布
07-12
你提供的这段 `PayController` 代码中,使用了 `[AbpAllowAnonymous]` 的方法: ```csharp [HttpPost] [AbpAllowAnonymous] public ResultDto CompleteOrderForTimer(Guid OrderId, string PaymentPassword, int UserId) ``` 这个 `[AbpAllowAnonymous]` 是**生效的**,而之前你在 `OrderRefundController` 中类似的方法上使用却没有生效。 下面我们来分析为什么这次它起作用了,以及在什么条件下 `[AbpAllowAnonymous]` 能够真正绕过 ABP 框架的身份验证。 --- ## ✅ 为什么这次 `[AbpAllowAnonymous]` 生效了? ### 1. **控制器层级没有全局 `[AbpAuthorize]`** 在 `OrderRefundController` 中你有如下定义: ```csharp [AbpAuthorize] public class OrderRefundController : ShopControllerBase ``` 这意味着整个控制器下的所有接口默认都需要授权。即使你在某个方法上加了 `[AbpAllowAnonymous]`,如果没有额外配置权限策略,ABP 默认不会允许匿名访问。 而在当前的 `PayController` 中,虽然也有 `[AbpAuthorize]`: ```csharp [AbpAuthorize] public class PayController : MallAppServiceBase ``` 但你在目标方法上明确加上了: ```csharp [AbpAllowAnonymous] ``` 而且这个方法是**公开供定时任务调用**的(比如通过后台 Job 或外部服务调用),这种场景下通常不需要登录用户上下文,所以框架允许匿名访问。 > 🟢 **结论:** 当前控制器虽然也受 `[AbpAuthorize]` 控制,但目标方法上加了 `[AbpAllowAnonymous]`,并且没有强制权限校验逻辑,因此生效了。 --- ### 2. **未设置权限限制** 如果某个方法没有绑定具体权限(如 `[AbpAuthorize("SomePermission")]`),仅使用 `[AbpAuthorize]` 在类级别,则 `[AbpAllowAnonymous]` 可以覆盖该行为。 换句话说: - 如果控制器上有 `[AbpAuthorize]` - 方法上有 `[AbpAllowAnonymous]` - 并且没有指定具体权限(如 `[AbpAuthorize("MyPermission")]`) 那么 ABP 会跳过身份验证。 --- ### 3. **可能的全局配置支持** 某些 ABP 项目会在模块初始化时添加如下配置: ```csharp Configuration.Authorization.IsAnonymousEnabled = true; ``` 这表示允许框架处理 `[AbpAllowAnonymous]` 标记的方法为匿名访问。 你可以检查你的模块类是否包含以下配置: ```csharp public class MyModule : AbpModule { public override void PreInitialize() { Configuration.Authorization.IsAnonymousEnabled = true; } } ``` 如果开启了这个选项,那 `[AbpAllowAnonymous]` 就能正常工作。 --- ## 🔍 对比总结 | 场景 | Controller 层级 `[AbpAuthorize]` | 方法层级 `[AbpAllowAnonymous]` | 是否生效 | 原因 | |------|-------------------------------|-----------------------------|----------|------| | `OrderRefundController` | ✅ 有 | ✅ 有 | ❌ 未生效 | 方法无单独权限控制,但被全局授权拦截 | | `PayController` | ✅ 有 | ✅ 有 | ✅ 生效 | 方法无权限绑定,且全局允许匿名访问 | --- ## ✅ 如何确保 `[AbpAllowAnonymous]` 总是生效? ### ✅ 方法一:开启全局匿名支持(推荐) 在模块 `PreInitialize` 中启用: ```csharp public override void PreInitialize() { Configuration.Authorization.IsAnonymousEnabled = true; } ``` 然后就可以放心地在方法上使用: ```csharp [AbpAllowAnonymous] public IActionResult SomePublicApi() ``` ### ✅ 方法二:显式定义“公开”权限并赋值给方法 ```csharp [AbpAuthorize("PublicAccess")] [AbpAllowAnonymous] public IActionResult SomePublicApi() ``` 并在权限系统中注册: ```csharp context.CreatePermission("PublicAccess").IsGrantedByDefault = true; ``` --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值