Skip to content

Commit

Permalink
[feat] OAuth登录失败时不要返回500。close #85
Browse files Browse the repository at this point in the history
  • Loading branch information
nnhy committed Oct 8, 2023
1 parent dbfc22f commit 7dd1810
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 112 deletions.
206 changes: 100 additions & 106 deletions NewLife.CubeNC/Common/AreaRegistrationBase.cs
Original file line number Diff line number Diff line change
@@ -1,141 +1,135 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using NewLife.Cube.Entity;
using NewLife.Cube.Membership;
using NewLife.Log;
using NewLife.Reflection;
using XCode;
using XCode.Membership;

namespace NewLife.Cube
{
/// <summary>区域特性基类</summary>
/// <remarks>
/// 提供以下功能:
/// 1,区域名称。从类名中截取。其中DisplayName特性作为菜单中文名。
/// 2,静态构造注册一次视图引擎、绑定提供者、过滤器
/// 3,注册区域默认路由
/// </remarks>
public class AreaBase : AreaAttribute
{
private static readonly ConcurrentDictionary<Type, Type> _areas = new();
namespace NewLife.Cube;

/// <summary>实例化区域注册</summary>
public AreaBase(String areaName) : base(areaName) => RegisterArea(GetType());
/// <summary>区域特性基类</summary>
/// <remarks>
/// 提供以下功能:
/// 1,区域名称。从类名中截取。其中DisplayName特性作为菜单中文名。
/// 2,静态构造注册一次视图引擎、绑定提供者、过滤器
/// 3,注册区域默认路由
/// </remarks>
public class AreaBase : AreaAttribute
{
private static readonly ConcurrentDictionary<Type, Type> _areas = new();

/// <summary>注册区域,每个继承此区域特性的类的静态构造函数都调用此方法,以进行相关注册</summary>
public static void RegisterArea<T>() where T : AreaBase => RegisterArea(typeof(T));
/// <summary>实例化区域注册</summary>
public AreaBase(String areaName) : base(areaName) => RegisterArea(GetType());

/// <summary>注册区域,每个继承此区域特性的类的静态构造函数都调用此方法,以进行相关注册</summary>
public static void RegisterArea(Type areaType)
{
if (!_areas.TryAdd(areaType, areaType)) return;
/// <summary>注册区域,每个继承此区域特性的类的静态构造函数都调用此方法,以进行相关注册</summary>
public static void RegisterArea<T>() where T : AreaBase => RegisterArea(typeof(T));

var ns = areaType.Namespace + ".Controllers";
var areaName = areaType.Name.TrimEnd("Area");
XTrace.WriteLine("开始注册权限管理区域[{0}],控制器命名空间[{1}]", areaName, ns);
/// <summary>注册区域,每个继承此区域特性的类的静态构造函数都调用此方法,以进行相关注册</summary>
public static void RegisterArea(Type areaType)
{
if (!_areas.TryAdd(areaType, areaType)) return;

// 更新区域名集合
var rs = CubeService.AreaNames?.ToList() ?? new List<String>();
if (!rs.Contains(areaName))
{
rs.Add(areaName);
CubeService.AreaNames = rs.ToArray();
}
var ns = areaType.Namespace + ".Controllers";
var areaName = areaType.Name.TrimEnd("Area");
XTrace.WriteLine("开始注册权限管理区域[{0}],控制器命名空间[{1}]", areaName, ns);

// 自动检查并添加菜单
var task = Task.Run(() =>
{
using var span = DefaultTracer.Instance?.NewSpan(nameof(ScanController), areaType.FullName);
try
{
ScanController(areaType);
}
catch (Exception ex)
{
span?.SetError(ex, null);
XTrace.WriteException(ex);
}
});
task.Wait(5_000);
// 更新区域名集合
var rs = CubeService.AreaNames?.ToList() ?? new List<String>();
if (!rs.Contains(areaName))
{
rs.Add(areaName);
CubeService.AreaNames = rs.ToArray();
}

/// <summary>自动扫描控制器,并添加到菜单</summary>
/// <remarks>默认操作当前注册区域的下一级Controllers命名空间</remarks>
protected static void ScanController(Type areaType)
// 自动检查并添加菜单
var task = Task.Run(() =>
{
var areaName = areaType.Name.TrimEnd("Area");
XTrace.WriteLine("start------初始化[{0}]的菜单体系------start", areaName);
using var span = DefaultTracer.Instance?.NewSpan(nameof(ScanController), areaType.FullName);
try
{
ScanController(areaType);
}
catch (Exception ex)
{
span?.SetError(ex, null);
XTrace.WriteException(ex);
}
});
task.Wait(5_000);
}

var mf = ManageProvider.Menu;
if (mf == null) return;
/// <summary>自动扫描控制器,并添加到菜单</summary>
/// <remarks>默认操作当前注册区域的下一级Controllers命名空间</remarks>
protected static void ScanController(Type areaType)
{
var areaName = areaType.Name.TrimEnd("Area");
XTrace.WriteLine("start------初始化[{0}]的菜单体系------start", areaName);

// 初始化数据库
_ = Menu.Meta.Count;
//_ = ModelTable.Meta.Count;
//_ = ModelColumn.Meta.Count;
var mf = ManageProvider.Menu;
if (mf == null) return;

//using var tran = (mf as IEntityFactory).Session.CreateTrans();
// 初始化数据库
_ = Menu.Meta.Count;
//_ = ModelTable.Meta.Count;
//_ = ModelColumn.Meta.Count;

//var menus = mf.ScanController(areaName, areaType.Assembly, areaType.Namespace + ".Controllers");
var menus = MenuHelper.ScanController(mf, areaName, areaType);
//using var tran = (mf as IEntityFactory).Session.CreateTrans();

// 更新区域名称为友好中文名
var menu = mf.Root.FindByPath(areaName);
if (menu != null && menu.DisplayName.IsNullOrEmpty())
{
var dis = areaType.GetDisplayName();
var des = areaType.GetDescription();
//var menus = mf.ScanController(areaName, areaType.Assembly, areaType.Namespace + ".Controllers");
var menus = MenuHelper.ScanController(mf, areaName, areaType);

if (!dis.IsNullOrEmpty()) menu.DisplayName = dis;
if (!des.IsNullOrEmpty()) menu.Remark = des;
// 更新区域名称为友好中文名
var menu = mf.Root.FindByPath(areaName);
if (menu != null && menu.DisplayName.IsNullOrEmpty())
{
var dis = areaType.GetDisplayName();
var des = areaType.GetDescription();

(menu as IEntity).Update();
}
if (!dis.IsNullOrEmpty()) menu.DisplayName = dis;
if (!des.IsNullOrEmpty()) menu.Remark = des;

//tran.Commit();
(menu as IEntity).Update();
}

//// 扫描模型表
//ScanModel(areaName, menus);
//tran.Commit();

// 再次检查菜单权限,因为上面的ScanController里开启菜单权限检查时,菜单可能还没有生成
var task = Task.Run(() =>
{
//Thread.Sleep(1000);
XTrace.WriteLine("新增了菜单,需要检查权限。二次检查,双重保障");
typeof(Role).Invoke("CheckRole");
});
task.Wait(5_000);
//// 扫描模型表
//ScanModel(areaName, menus);

XTrace.WriteLine("end---------初始化[{0}]的菜单体系---------end", areaName);
}
// 再次检查菜单权限,因为上面的ScanController里开启菜单权限检查时,菜单可能还没有生成
var task = Task.Run(() =>
{
//Thread.Sleep(1000);
XTrace.WriteLine("新增了菜单,需要检查权限。二次检查,双重保障");
typeof(Role).Invoke("CheckRole");
});
task.Wait(5_000);

private static ICollection<String> _namespaces;
XTrace.WriteLine("end---------初始化[{0}]的菜单体系---------end", areaName);
}

/// <summary>判断控制器是否归属于魔方管辖</summary>
/// <param name="controllerActionDescriptor"></param>
/// <returns></returns>
public static Boolean Contains(ControllerActionDescriptor controllerActionDescriptor)
{
// 判断控制器是否在管辖范围之内
var controller = controllerActionDescriptor.ControllerTypeInfo;
var ns = controller.Namespace;
if (!ns.EndsWith(".Controllers")) return false;
private static ICollection<String> _namespaces;

_namespaces ??= new HashSet<String>(_areas.Keys.Select(e => e.Namespace));
/// <summary>判断控制器是否归属于魔方管辖</summary>
/// <param name="controllerActionDescriptor"></param>
/// <returns></returns>
public static Boolean Contains(ControllerActionDescriptor controllerActionDescriptor)
{
// 判断控制器是否在管辖范围之内
var controller = controllerActionDescriptor.ControllerTypeInfo;
var ns = controller.Namespace;
if (!ns.EndsWith(".Controllers")) return false;

// 该控制器父级命名空间必须有对应的区域注册类,才会拦截其异常
ns = ns.TrimEnd(".Controllers");
return _namespaces.Contains(ns);
}
_namespaces ??= new HashSet<String>(_areas.Keys.Select(e => e.Namespace));

/// <summary>获取所有区域</summary>
/// <returns></returns>
public static ICollection<Type> GetAreas() => _areas.Keys;
// 该控制器父级命名空间必须有对应的区域注册类,才会拦截其异常
ns = ns.TrimEnd(".Controllers");
return _namespaces.Contains(ns);
}

/// <summary>获取所有区域</summary>
/// <returns></returns>
public static ICollection<Type> GetAreas() => _areas.Keys;
}
3 changes: 1 addition & 2 deletions NewLife.CubeNC/Common/EntityAuthorizeAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Extensions;
Expand Down
17 changes: 13 additions & 4 deletions NewLife.CubeNC/Controllers/SsoController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using NewLife.Cube.Web.Models;
using NewLife.Log;
using NewLife.Model;
using NewLife.Net;
using NewLife.Remoting;
using NewLife.Security;
using NewLife.Web;
Expand Down Expand Up @@ -82,12 +83,20 @@ static SsoController()
public virtual ActionResult Login(String name)
{
var prov = Provider;
var client = prov.GetClient(name);
client.Init(GetUserAgent());

var rurl = prov.GetReturnUrl(Request, true);

return base.Redirect(OnLogin(client, null, rurl, null));
try
{
var client = prov.GetClient(name);
client.Init(GetUserAgent());

return base.Redirect(OnLogin(client, null, rurl, null));
}
catch (InvalidOperationException)
{
var retUrl = "~/Admin/User/Login".AppendReturn(rurl);
return Redirect(retUrl);
}
}

private String OnLogin(OAuthClient client, String state, String returnUrl, OAuthLog log)
Expand Down
1 change: 1 addition & 0 deletions NewLife.CubeNC/WebMiddleware/RunTimeMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public async Task Invoke(HttpContext ctx)
var userAgent = ctx.Request.Headers["User-Agent"] + "";
var ua = new UserAgentParser();
ua.Parse(userAgent);
ctx.Items["UserAgent"] = ua;

// 识别拦截爬虫
if (!ValidRobot(ctx, ua)) return;
Expand Down

0 comments on commit 7dd1810

Please sign in to comment.