来吧学学.Net Core之登录认证与跨域资源使用

序言

学习core登录认证与跨域资源共享是越不过的砍,所以我在学习中同样也遇到啦这两个问题,今天我们就用示例来演示下使用下这2个技术点吧.

本篇主要内容如下:

1、展示一个登录认证的简单示例

2、跨域资源访问

3、跨域获取登录认证的用户信息

.Net Core使用身份认证(Authentication,Identity)制作登录认证功能

首先我们实现登录这个功能,代码如下

    [Authorize]
    public class AccountController : Controller
    {
        [HttpGet]
        [AllowAnonymous]
        public IActionResult Login(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (this.User.Identity.IsAuthenticated)
            {
                return RedirectPermanent(returnUrl);
            }
            return View();
        }
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> Login(string userName, string password,string returnUrl=null)
        {
            ViewData["ReturnUrl"] = returnUrl;          
            if (!string.IsNullOrEmpty(userName) && userName == password)
            {
                var claims = new List<Claim>(){
                              new Claim(ClaimTypes.Name,userName),new Claim("password",password),new Claim("realname","张龙豪")
                           };
                //init the identity instances 
                var userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
                //signin 
                await HttpContext.Authentication.SignInAsync("CookieAuth", userPrincipal, new AuthenticationProperties
                {
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
                    IsPersistent = false,
                    AllowRefresh = false
                });
                return RedirectPermanent(returnUrl);
            }
            else
            {
                ViewBag.ErrMsg = "UserName or Password is invalid";
                return View();
            }
        }

前台代码如下

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Login</title>
</head>
<body>
    <form asp-controller="Account" asp-action="Login" method="post" class="form-horizontal" asp-route-returnurl="@ViewData["ReturnUrl"]" role="form">
        <div class="form-group">
            <label class="col-md-2 control-label">UserName</label>
            <div class="col-md-10">
                <input type="text" name="username" />
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-2 control-label">Password</label>
            <div class="col-md-10">
                <input type="password" name="password" />
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <button type="submit" class="btn btn-default">Log in</button>
            </div>
        </div>
    </form>
</body>
</html>

在Startup文件的Configure方法中加入下面代码

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {          
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationScheme = "CookieAuth",   //认证方案:这是一个已知中间件的值,当有多个实例的中间件如果你想限制授权到一个实例时这个选项将会起作用。
                LoginPath = new PathString("/Account/Login"), //登录路径:这是当用户试图访问资源但未经过身份验证时,程序将会将请求重定向到这个相对路径。
                AccessDeniedPath = new PathString("/Account/Forbidden"),  //禁止访问路径:当用户试图访问资源时,但未通过该资源的任何授权策略,请求将被重定向到这个相对路径。
                AutomaticAuthenticate = true,  //自动认证:这个标志表明中间件应该会在每个请求上进行验证和重建他创建的序列化主体。                
                AutomaticChallenge = true,  //自动挑战:这个标志标明当中间件认证失败时应该重定向浏览器到登录路径或者禁止访问路径。
                SlidingExpiration = true,  //Cookie可以分为永久性的和临时性的。 临时性的是指只在当前浏览器进程里有效,浏览器一旦关闭就失效(被浏览器删除)。 永久性的是指Cookie指定了一个过期时间,在这个时间到达之前,此cookie一直有效(浏览器一直记录着此cookie的存在)。 slidingExpriation的作用是,指示浏览器把cookie作为永久性cookie存储,但是会自动更改过期时间,以使用户不会在登录后并一直活动,但是一段时间后却自动注销。也就是说,你10点登录了,服务器端设置的TimeOut为30分钟,如果slidingExpriation为false,那么10:30以后,你就必须重新登录。如果为true的话,你10:16分时打开了一个新页面,服务器就会通知浏览器,把过期时间修改为10:46。 更详细的说明还是参考MSDN的文档。
                CookieHttpOnly = false  //默认为true
            });

好啦,你可以看到有[Authorize]属性的方法或者控制器都需要登录才能访问,如果没有登录是不允许访问的.

接下来你可能需要获取当前登录用户的用户信息,代码如下:

        [HttpPost]
        public string GetCurrUserRealname()
        {
            var s = this.User.Identities.First(u => u.IsAuthenticated).FindFirst("realname").Value;
            var ss = this.User.Identity.Name;
            return ss + ":" + s;
        }
 $.post("/Account/GetCurrUserRealname", null, function (data) { $("#content").html(data); });

ok,这样就能获取到当前登录的用户信息

那如何退出呢?代码如下:

        public async Task<JsonResult> Logout()
        {
            await HttpContext.Authentication.SignOutAsync("CookieAuth");
            return Json(new { data = "验证方案:CookieAuth退出成功" });
        }

这样看来完整的登录验证就完成啦,但是目前位置,我的代码都还简单的要命,只能初学者拿来入手,具体还有很多东西可以扩展.我们需要自己思考学习.

.Net Core跨域资源访问

那这个跨域的环境呢,需要我们自己搞一下.怎么搞,如下

本地测试前期准备

1.首先我们搞两个core的站点

 

2.本地host配置两个域名,并在项目中做如下设置

hosts如下:

网站的launchSettings.json文件中配置项目CoreCorsATest为 "applicationUrl": "http://b.local.com:63455/",  项目AuthentiactionTest为 "applicationUrl": "http://a.local.com:50307/".

3. 实验约定:

我们在项目AuthentiactionTest中写接口,项目CoreCorsATest中调用AuthentiactionTest中的接口.

不做任何处理写接口跨域调用

AuthentiactionTest中写下如下接口

 public class HomeController : Controller
    {
        public string GetName()
        {
            return "张龙豪";
        }

CoreCorsATest中如下调用

$.post("http://a.local.com:50307/Home/GetName", null, function (data) { $("#content").html(data); });

结果如下:接口调用成功,但是跨域资源不允许使用

解决问题

设置跨域的域名

 public void ConfigureServices(IServiceCollection services)
        {
            //services.AddAuthorization();
            // Add framework services.
            services.AddMvc();
            services.AddCors(options => options.AddPolicy("AllowSameDomain", builder => builder.WithOrigins("http://a.local.com:50307", "http://b.local.com:63455")));
        }

下面的两种调用方式

  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
           app.UseCors("AllowSameDomain");
 public class HomeController : Controller
    {
        [EnableCors("AllowSameDomain")]
        public string GetName()
        {
            return "张龙豪";
        }

.Net Core跨域访问需要登录认证的资源

这个问题就是上面跨域访问的资源如果出现 [Authorize]特性,或者是访问当前用户的登录信息,用刚才的方法是不行的.

登录使用,上述的登录功能,接口如下

        [HttpPost]
        public string GetCurrUserRealname()
        {
            var s = this.User.Identities.First(u => u.IsAuthenticated).FindFirst("realname").Value;
            var ss = this.User.Identity.Name;
            return ss + ":" + s;
        }

那在b.local.com 这个域名下怎么访问才是有效的呢?

需要下面两部操作

1.设置接口服务项目配置,如下操作

services.AddCors(options => options.AddPolicy("AllowSameDomain", builder => builder.WithOrigins("http://a.local.com:50307", "http://b.local.com:63455").AllowCredentials()));

2.ajax访问接口时

 $.ajax({
            type: 'POST',
            url: "http://a.local.com:50307/Account/GetCurrUserRealname",
            data: null,
            dataType: "json",
            xhrFields: {
                withCredentials: true
            },
            success: function (result) {
                $("#message").html(result);
            }
        });

ok,这样就可以访问到当前登录用户的信息啦

总结

本篇呢,写的都是用例,理论原理,没有涉及,也有一些其他常用额扩展点,都没有涉及到.

这里我只是把一些的点,贴出来,希望对想入手core的同学有所帮助.如有志同道合者,欢迎加左上方群,一起学习进步.

posted @ 2017-06-27 19:10  张龙豪  阅读(8201)  评论(5编辑  收藏  举报