我想防止直接访问视图。单击用户电子邮件中的确认链接时,我有一个显示“电子邮件已确认”的视图。但是,问题在于该视图的网址可以直接访问,我只是希望在单击电子邮件中的链接时可以访问该视图。
我已经尝试过此选项,但是由于 UrlReferer 在Asp.net核心中不可用,因此会不断出错。该代码无法在asp.net核心中运行,请有人帮我。
如何在ASp.net Core 2.x中访问这些值:
filterContext.HttpContext.Request.UrlReferrer
filterContext.HttpContext.Request.Url.Host
filterContext.HttpContext.Request.UrlReferrer.Host
我在Stack-overflow上找到的代码-但它需要System.Web,在asp.net核心中不可用。
public class NoDirectAccessAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.UrlReferrer == null ||
filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }));
}
}
}
使用自定义属性的推荐方式
[NoDirectAccess]
public ActionResult MyActionMethod()
答案 0 :(得分:0)
UrlReferer
,请如下创建过滤器: public class NoDirectAccessAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var canAcess= false;
// check the refer
var referer= filterContext.HttpContext.Request.Headers["Referer"].ToString();
if(!string.IsNullOrEmpty(referer)){
var rUri = new System.UriBuilder(referer).Uri;
var req = filterContext.HttpContext.Request;
if(req.Host.Host==rUri.Host && req.Host.Port == rUri.Port && req.Scheme == rUri.Scheme ){
canAcess=true;
}
}
// ... check other requirements
if(!canAcess){
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }));
}
}
}
现在您可以使用[NoDirectAccess]
装饰您的操作方法:
[NoDirectAccess]
public IActionResult Privacy()
{
return View();
}
Referer
来授权请求,因为伪造UrlReferer
的HTTP标头很容易。 IMO,最好将EmailConfirmed=true
存储在用户单击确认链接时的某个位置。然后,您可以在验证时检查EmailConfirmed
是否等于true
。
public class NoDirectAccessAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var canAcess= false;
// check the `EmailConfirmed` state
// ... check other requirements
if(!canAcess){
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }));
}
}
}
答案 1 :(得分:0)
通常,在请求上依赖“ referer”属性不是一个好主意。浏览器的实现可能会有所不同,结果您可能会收到不一致的值。
如果URL是“公共”,则不能阻止用户在浏览器上键入该URL。但是,您可以做的是在“获取”请求中添加验证-例如,需要URL上的一些其他信息-在您的情况下,说出用户ID和验证“代码”。这就是asp.net身份生成用于电子邮件确认的URL的方式。它包括用户ID和确认代码。如果没有这些值作为URL的一部分,则可以使请求无效并重定向到另一个页面(而不是通过电子邮件确认的页面)。
例如,在Razor页面中,以下是如何验证请求的示例。 (关键是,它需要来自用户的其他输入而不是纯URL。)(您也可以在MVC中执行类似的操作。)
public async Task<IActionResult> OnGetAsync(string userId, string code)
{
if (userId == null || code == null)
{
return RedirectToPage("/Index");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{userId}'.");
}
var result = await _userManager.ConfirmEmailAsync(user, code);
if (!result.Succeeded)
{
throw new ApplicationException($"Error confirming email for user with ID '{userId}':");
}
return Page();
}
用于验证上述代码的URL类似于以下内容:
http://[baseurl]/Account/ConfirmEmail?userId=ca5416dd-c93a-49a5-8fac-a9986dc91ed7&code=CfDJ8DWvHoaRg6JAv0rZ75jyEVx