Authourize标签不能正确维护Asp.net Core Identity ..中的会话状态。

时间:2018-08-08 07:43:07

标签: asp.net-core

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using HMS_Context;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Http.Features;
    using HMS_Service.Services.MasterService;
    using HMS_Service.Services.PatientVisitService;
    using HMS_Service.UserManagementService;
    using HMS_Service.Services.PatientRegistrationService;
    using HMS_Service.Services.BloodCampService;
    using HMS_Service.Services.AccountService;
    using System;
    using Microsoft.AspNetCore.Identity;
    using HMS_Presentation.Services;
    using HMS_Service.Services.InventoryManagementService;
    using HMS_Service.Services.SystemManagementService;
    using HMS_Service.Services.UserManagementService;
    using HMS_Service.Services.LabManagementService;
    using HMS_Service.CacheSetting.AppSettings;
    using HMS_Service.Services.BarCodeService;

    namespace HMS_Presentation
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }

            public IConfiguration Configuration { get; }

            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<IAppSettings, AppSettings>();
                services.AddMemoryCache();
                services.AddOptions();
                services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
                services.AddDbContext<_DbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
                services.AddIdentity<HMS_POCO.UserManagement.ApplicationUser, HMS_POCO.UserManagement.ApplicationRole>(
                   option => {

                       option.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                       option.Lockout.MaxFailedAccessAttempts = 5;
                       option.Lockout.AllowedForNewUsers = false;

                   })
                  .AddEntityFrameworkStores<HMS_Context._DbContext>()
                  .AddDefaultTokenProviders();
                /*Cache Functionality Start*/


                /*Cache Functionality End*/



                services.AddAuthorization(options =>
                {
                    options.AddPolicy("Administrator", policy => policy.RequireRole("Admin","Superior"));
                    options.AddPolicy("Doctors", policy => policy.RequireRole("Receptionist","Doctor", "Superior"));
                    options.AddPolicy("Nurses", policy => policy.RequireRole("Nurse", "Superior"));
                    options.AddPolicy("Labortory", policy => policy.RequireRole("LabTech", "Superior"));
                    options.AddPolicy("Accountants", policy => policy.RequireRole("Accountant", "Superior")); 
                    options.AddPolicy("Receptionist", policy => policy.RequireRole("Receptionist", "Superior"));
                    options.AddPolicy("RecpDoct", policy => policy.RequireRole("Receptionist","Doctor", "Superior"));
                    options.AddPolicy("RMO", policy => policy.RequireRole("RMO", "Superior"));
                    options.AddPolicy("RD", policy => policy.RequireRole("RMO", "Doctor","Superior"));
                    // Access DNL(Doctor,Nurse ,Lab)
                    options.AddPolicy("AccessDNL", policy => policy.RequireRole("Doctor", "Nurse", "LabTech", "Superior"));

                });



                services.ConfigureApplicationCookie(options =>
                {

                    options.Cookie.Name = "YourAppCookieName";
                    options.LoginPath = "/UserAccount/Login";
                    options.LogoutPath = "/UserAccount/Logout";
                    options.AccessDeniedPath = "/UserAccount/AccessDenied";
                    options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
                });

                services.AddDistributedMemoryCache();
                services.AddSession(options=>options.Cookie.HttpOnly=true);

                services.AddMvc().AddSessionStateTempDataProvider();

                services.AddTransient<IEmailSender, EmailSender>();
                services.Configure<FormOptions>(x => {
                    x.ValueLengthLimit = int.MaxValue;
                    x.MultipartBodyLengthLimit = long.MaxValue;
                    x.BufferBodyLengthLimit = long.MaxValue;
                    x.MemoryBufferThreshold = int.MaxValue;
                    x.ValueCountLimit = int.MaxValue;
                });



            }

            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseBrowserLink();

                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                }
                app.UseSession();
                app.UseStaticFiles();
                app.UseAuthentication();
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",

                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }


**User Account Controller** 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using HMS_Presentation.Services;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authentication;
using HMS_Presentation.Models.AccountViewModels;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Security.Claims;
using HMS_Service.UserManagementService;
using Microsoft.AspNetCore.Http;
using HMS_Service.Services.UserManagementService;
using HMS_POCO.UserManagement;

namespace HMS_Presentation.Controllers
{
    [Authorize(Policy = "Administrator")]   
    [Route("[controller]/[action]")]
    public class UserAccountController : Controller
    {
        private readonly UserManager<HMS_POCO.UserManagement.ApplicationUser> _userManager;
        private readonly SignInManager<HMS_POCO.UserManagement.ApplicationUser> _signInManager;
        private readonly IEmailSender _emailSender;
        private readonly ILogger _logger;
        private readonly RoleManager<HMS_POCO.UserManagement.ApplicationRole> _roleManager;

        //Extra Addition
        private readonly EmployeeService _employeeService;
        private readonly UserAccessLogService _userAccessLogService;
        public UserAccountController(
            UserManager<HMS_POCO.UserManagement.ApplicationUser> userManager,
            SignInManager<HMS_POCO.UserManagement.ApplicationUser> signInManager,
            IEmailSender emailSender,
            ILogger<UserAccountController> logger,
            RoleManager<HMS_POCO.UserManagement.ApplicationRole> roleManager,
            EmployeeService employeeService, UserAccessLogService userAccessLogService)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _emailSender = emailSender;
            _logger = logger;
            _roleManager = roleManager;
            _employeeService = employeeService;
            _userAccessLogService = userAccessLogService;
        }

        [TempData]
        public string ErrorMessage { get; set; }

        [HttpGet]
        [AllowAnonymous]

        public async Task<IActionResult> Login(string returnUrl = null)
        {
            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            USER_ACCESS_LOG be = new USER_ACCESS_LOG();
            be.AccessTime = DateTime.Now.ToString();
            be.UserName = model.Email;

            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
                if (result.Succeeded)
                {
                    var lookupUser = _userManager.Users.Where(c => c.UserName == model.Email).FirstOrDefault();
                    HttpContext.Session.SetInt32("UserId", lookupUser.EmpId);
                    _logger.LogInformation("User logged in.");
                    be.AccessedStatus = true;
                    _userAccessLogService.Add(be);
                    return RedirectToLocal(returnUrl);
                }
                if (result.RequiresTwoFactor)
                {
                    var lookupUser = _userManager.Users.Where(c => c.UserName == model.Email).FirstOrDefault();
                    HttpContext.Session.SetInt32("UserId", lookupUser.EmpId);
                    return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToAction(nameof(Lockout));
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    be.AccessedStatus = false;
                    _userAccessLogService.Add(be);
                    return View(model);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> LoginWith2fa(bool rememberMe, string returnUrl = null)
        {
            // Ensure the user has gone through the username & password screen first
            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

            if (user == null)
            {
                throw new ApplicationException($"Unable to load two-factor authentication user.");
            }

            var model = new LoginWith2faViewModel { RememberMe = rememberMe };
            ViewData["ReturnUrl"] = returnUrl;

            return View(model);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = null)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
            if (user == null)
            {
                throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
            }

            var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);

            var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine);

            if (result.Succeeded)
            {
                _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id);
                return RedirectToLocal(returnUrl);
            }
            else if (result.IsLockedOut)
            {
                _logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                _logger.LogWarning("Invalid authenticator code entered for user with ID {UserId}.", user.Id);
                ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
                return View();
            }
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> LoginWithRecoveryCode(string returnUrl = null)
        {
            // Ensure the user has gone through the username & password screen first
            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
            if (user == null)
            {
                throw new ApplicationException($"Unable to load two-factor authentication user.");
            }

            ViewData["ReturnUrl"] = returnUrl;

            return View();
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> LoginWithRecoveryCode(LoginWithRecoveryCodeViewModel model, string returnUrl = null)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
            if (user == null)
            {
                throw new ApplicationException($"Unable to load two-factor authentication user.");
            }

            var recoveryCode = model.RecoveryCode.Replace(" ", string.Empty);

            var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);

            if (result.Succeeded)
            {
                _logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id);
                return RedirectToLocal(returnUrl);
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                _logger.LogWarning("Invalid recovery code entered for user with ID {UserId}", user.Id);
                ModelState.AddModelError(string.Empty, "Invalid recovery code entered.");
                return View();
            }
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult Lockout()
        {
            return View();
        }

        [HttpGet]
        public IActionResult Register(string returnUrl = null)
        {
            ViewData["RoleName"] = new SelectList(_roleManager.Roles, "Id", "Name");
            ViewData["EmployeeName"] = new SelectList(_employeeService.GetUnRegisteredEmployee(), "Id", "FirstName");
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                var user = new HMS_POCO.UserManagement.ApplicationUser { UserName = model.Email, Email = model.Email, EmpId=model.EmployeeId};
                var result = await _userManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    IdentityRole res = await _roleManager.FindByIdAsync(model.RoleId);
                    await _userManager.AddToRoleAsync(user, res.Name);


                    _logger.LogInformation("User created a new account with password.");
                    return RedirectToLocal(returnUrl);
                }
                AddErrors(result);
            }

            ViewData["RoleName"] = new SelectList(_roleManager.Roles, "Id", "Name");
            ViewData["EmployeeName"] = new SelectList(_employeeService.GetAll(), "Id", "FirstName");
            return View(model);
        }

        [AllowAnonymous]
        public async Task<IActionResult> Logout()
        {
            HttpContext.Session.Clear();
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            return RedirectToAction(nameof(HomeController.Index), "Home");
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public IActionResult ExternalLogin(string provider, string returnUrl = null)
        {
            // Request a redirect to the external login provider.
            var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
            var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
            return Challenge(properties, provider);
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
        {
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return RedirectToAction(nameof(Login));
            }
            var info = await _signInManager.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return RedirectToAction(nameof(Login));
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
                return RedirectToLocal(returnUrl);
            }
            if (result.IsLockedOut)
            {
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                // If the user does not have an account, then ask the user to create an account.
                ViewData["ReturnUrl"] = returnUrl;
                ViewData["LoginProvider"] = info.LoginProvider;
                var email = info.Principal.FindFirstValue(ClaimTypes.Email);
                return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
            }
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null)
        {
            if (ModelState.IsValid)
            {
                // Get the information about the user from the external login provider
                var info = await _signInManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    throw new ApplicationException("Error loading external login information during confirmation.");
                }
                var user = new HMS_POCO.UserManagement.ApplicationUser { UserName = model.Email, Email = model.Email };
                var result = await _userManager.CreateAsync(user);
                if (result.Succeeded)
                {
                    result = await _userManager.AddLoginAsync(user, info);
                    if (result.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, isPersistent: false);
                        _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
                        return RedirectToLocal(returnUrl);
                    }
                }
                AddErrors(result);
            }

            ViewData["ReturnUrl"] = returnUrl;
            return View(nameof(ExternalLogin), model);
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ConfirmEmail(string userId, string code)
        {
            if (userId == null || code == null)
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
            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);
            return View(result.Succeeded ? "ConfirmEmail" : "Error");
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ForgotPassword()
        {
            return View();
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByEmailAsync(model.Email);
                if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
                {
                    // Don't reveal that the user does not exist or is not confirmed
                    return RedirectToAction(nameof(ForgotPasswordConfirmation));
                }

                // For more information on how to enable account confirmation and password reset please
                // visit https://go.microsoft.com/fwlink/?LinkID=532713
                var code = await _userManager.GeneratePasswordResetTokenAsync(user);
                var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme);
                await _emailSender.SendEmailAsync(model.Email, "Reset Password",
                   $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
                return RedirectToAction(nameof(ForgotPasswordConfirmation));
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ForgotPasswordConfirmation()
        {
            return View();
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ResetPassword(string code = null)
        {
            if (code == null)
            {
                throw new ApplicationException("A code must be supplied for password reset.");
            }
            var model = new ResetPasswordViewModel { Code = code };
            return View(model);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            var user = await _userManager.FindByEmailAsync(model.Email);
            if (user == null)
            {
                // Don't reveal that the user does not exist
                return RedirectToAction(nameof(ResetPasswordConfirmation));
            }
            var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction(nameof(ResetPasswordConfirmation));
            }
            AddErrors(result);
            return View();
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ResetPasswordConfirmation()
        {
            return View();
        }


        [HttpGet]
        public IActionResult AccessDenied()
        {
            return View();
        }

        #region Helpers

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
        }
        #endregion
    }
}

这是我的Startup.cs文件的代码。和用户帐户控制器authorize标记不能正确保持会话状态..即使经过会话时间之后,应用程序仍可启动,无需电子邮件和密码。如何解决。我正在使用.NET CORE和Visual Studio 2017,当我注销然后运行该应用程序时,它可以正常工作并接受电子邮件和密码。但没有注销该帐户并关闭选项卡,然后运行该应用程序时出现问题...

1 个答案:

答案 0 :(得分:0)

在下面提到的默认登录方法中使用IsPersistent=true

var result = await _signInManager.PasswordSignInAsync(user, model.LoginPassword, true, false);

第三个参数是IsPersistent,对于永久登录应该为true。