Monday, 20 March 2017

aspcore authorize2 sessions async timed logout

long time no log in, need log in again

logged in successful, redirect to main page

redirect to second page: server redirect to index action to verify authentication, if pass, redirect to second page

logged out
logged in again


//controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Authorize2.Models;
using Microsoft.EntityFrameworkCore;

namespace Authorize2.Controllers
{
    public class AuthorizeController : Controller
    {
        private Authorize2Context DB;

        public AuthorizeController(Authorize2Context context)
        {
            DB = context;
        }

        // GET: Authorize
        public async Task<IActionResult> Index()
        {
            var previous_page = HttpContext.Session.GetString("URL");

            HttpContext.Session.SetString("URL", "Index");

            var machine = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();

            var exist_login_record = await DB.LoginRecord.FirstOrDefaultAsync(x => x.Computer == machine);

            //if computer not registered, register computer, redirect to log in page
            if (exist_login_record == null)
            {
                DB.LoginRecord.Add(new LoginRecord { Computer = machine });
                await DB.SaveChangesAsync();
            }
            else
            {
                //if computer is registered, and user logged in, redirect to Main page, otherwise redirect to login              
                if (exist_login_record.UserId != null)
                {
                    TimeSpan timespan_since_last_login = (TimeSpan)(DateTime.Now - exist_login_record.LastLogin);

                    //if already logged in and last log in within 30 second ago
                    if (timespan_since_last_login.TotalSeconds < 30)
                    {
                        exist_login_record.LastLogin = DateTime.Now;
                        await DB.SaveChangesAsync();

                        var user = await DB.User.FirstOrDefaultAsync(x => x.Id == exist_login_record.UserId);

                        var log_information = machine + "!" + DateTime.Now.ToString() + "!" + user.Name;

                        HttpContext.Session.SetString("Log_info", log_information);

                        if (previous_page != null && previous_page != "Index")
                        {
                            return RedirectToAction(previous_page);
                        }
                        else
                        {
                            return RedirectToAction("Mainpage");
                        }
                    }

                    ViewBag.error_message = "inactive for a long time, please log in again";
                }
            }

            ViewBag.login_record_viewbag = new login_record_dto { computer = machine, last_login = new DateTime(2000, 1, 1, 0, 0, 0), user = "" };

            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Index(IFormCollection collection)
        {
            HttpContext.Session.SetString("URL", "Index");

            var user = collection["ux_user"];
            var password = collection["ux_password"];

            var machine = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();

            var exist_login_record = await DB.LoginRecord.FirstOrDefaultAsync(x => x.Computer == machine);

            var user_password_match = false;
            int user_id = 0;

            foreach (var item in DB.User)
            {
                if (item.Name.Replace(" ", string.Empty) == user && item.Password.Replace(" ", string.Empty) == password)
                {
                    user_password_match = true;
                    user_id = item.Id;
                }
            }

            //if log in correct, update record, redirect to mainpage
            if (user_password_match)
            {
                exist_login_record.UserId = user_id;
                exist_login_record.LastLogin = DateTime.Now;
                await DB.SaveChangesAsync();

                var log_information = machine + "!" + DateTime.Now.ToString() + "!" + user;

                HttpContext.Session.SetString("Log_info", log_information);

                return RedirectToAction("Mainpage");
            }

            ViewBag.login_record_viewbag = new login_record_dto { computer = machine, last_login = new DateTime(2000, 1, 1, 0, 0, 0), user = "" };
            ViewBag.error_message = "user name, password not match";

            return View();
        }

        public ActionResult Mainpage()
        {
            //if mainpage is not redirected from Index, redirect to Index to check log in
            if (HttpContext.Session.GetString("URL") != "Index")
            {
                HttpContext.Session.SetString("URL", "Mainpage");

                return RedirectToAction("Index");
            }

            HttpContext.Session.SetString("URL", "Mainpage");

            var log_information = HttpContext.Session.GetString("Log_info").Split('!');

            ViewBag.login_record_viewbag = new login_record_dto
            {
                computer = log_information[0],
                last_login = Convert.ToDateTime(log_information[1]),
                user = log_information[2]
            };

            return View();
        }

        public ActionResult secondary_page()
        {
            if (HttpContext.Session.GetString("URL") != "Index")
            {
                HttpContext.Session.SetString("URL", "secondary_page");

                return RedirectToAction("Index");
            }

            HttpContext.Session.SetString("URL", "secondary_page");

            var log_information = HttpContext.Session.GetString("Log_info").Split('!');

            ViewBag.login_record_viewbag = new login_record_dto
            {
                computer = log_information[0],
                last_login = Convert.ToDateTime(log_information[1]),
                user = log_information[2]
            };

            return View();
        }

        public async Task<IActionResult> LogOut()
        {
            var machine = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();

            var exist_login_record = await DB.LoginRecord.FirstOrDefaultAsync(x => x.Computer == machine);

            if (exist_login_record != null)
            {
                exist_login_record.UserId = null;
                DB.SaveChanges();
            }

            return  RedirectToAction("Index");
        }
    }
}

-------------------------------------------------------------------

//mainpage.cshtml

<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">

    var computer = '@ViewBag.login_record_viewbag.computer';
    var last_login_time = '@ViewBag.login_record_viewbag.last_login';
    var user = '@ViewBag.login_record_viewbag.user';

    //webpage open event
    $(document).ready(function () {

        $('#log_lable').text(user + ' last logged in ' + computer + ' at ' + last_login_time);
    });

</script>


<h2>Main Page</h2>

<div class="text-right">
    <label id="log_lable"></label>
</div>

<br/>
<a href="/Authorize/Logout">logout</a>
<a>      |      </a>
<a href="/Authorize/secondary_page">secondary page</a>

----------------------------------------------------------

//startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Authorize2.Data;
using Authorize2.Models;
using Authorize2.Services;

namespace Authorize2
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

            if (env.IsDevelopment())
            {
                // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
                builder.AddUserSecrets<Startup>();
            }

            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddMvc();
            services.AddDistributedMemoryCache(); 
            services.AddSession();

            var cs = Configuration.GetConnectionString("SqlConnection");
            services.AddDbContext<Authorize2Context>(options => options.UseSqlServer(cs));

            // Add application services.
            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();
        }

        // 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)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseIdentity();

            // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715

            // IMPORTANT: This session call MUST go before UseMvc()
            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}



reference:
http://stackoverflow.com/questions/22564846/c-sharp-compare-two-datetimes
http://stackoverflow.com/questions/16346146/remove-all-whitespace-from-c-sharp-string-with-regex

sessions
http://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/
http://stackoverflow.com/questions/33814042/using-tempdata-is-crashing-my-application

No comments:

Post a Comment