Hi guys, I'm having a problem with my system authorization, I will give a quick explanation of how it works, my system is using FormsAuthentication to login, so it uses a custom AuthorizeAttribute where it user permissions on controllers and action,
This AuthorizeAttribute works so we have a Profile table and a menus table, so it gets more dynamic, but we noticed a problem when creating / editing a profile it keeps the old Authorization until the application is restarted in the visual or in the environment restart session.
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Routing;
-
- namespace macpartner.Models.CustomAuthorise
- {
- public class AuthorizedAction : AuthorizeAttribute
- {
-
- protected override bool AuthorizeCore(HttpContextBase httpContext)
- {
-
- var isAuthorized = base.AuthorizeCore(httpContext);
- if (!isAuthorized)
- {
- return false;
- }
-
- var routeData = httpContext.Request.RequestContext.RouteData;
- string action = routeData.GetRequiredString("action");
- string controller = routeData.GetRequiredString("controller");
-
- return MyCustomDbAccessLayer.IsUserAuthorized(httpContext.User.Identity.Name, action, controller);
- }
- }
-
- public class MyCustomDbAccessLayer : IDisposable
- {
- private static MacPartnerContext db = new MacPartnerContext();
-
- public static bool IsUserAuthorized(string username, string action, string controller)
- {
-
- action = action.ToLowerInvariant();
- controller = controller.ToLowerInvariant();
-
- var user = db.Users.Where(tp => tp.UserName == username).FirstOrDefault();
- if (user != null)
- {
- var perfil = db.Perfils.Find(user.PerfilId);
-
- var acesso = perfil.MenusId.Where(c => c.Controller.ToLowerInvariant() == controller && c.Action.ToLowerInvariant() == action).FirstOrDefault();
-
- if (acesso != null)
- {
- return true;
-
- }
- else
- {
- return false;
- }
-
- }
- else
- {
- return false;
- }
-
- }
-
- public void Dispose()
- {
- db.Dispose();
- }
- }
- }
- using macpartner.Classes;
- using macpartner.Helpers;
- using macpartner.Models;
- using macpartner.Models.CustomAuthorise;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Security;
-
- namespace macpartner.Controllers.MVC
- {
- public class ContaController : Controller
- {
- private MacPartnerContext db = new MacPartnerContext();
-
-
-
-
-
- [HttpGet]
- [AllowAnonymous]
- public ActionResult Register()
- {
- return View();
- }
-
-
-
-
-
- [HttpPost]
- [AllowAnonymous]
- [ValidateAntiForgeryToken]
- public async Task<ActionResult> Register(User user)
- {
-
- string message = "";
-
- user.ActivationCode = Guid.NewGuid();
- user.Password = Crypto.Encrypt(user.Password);
- user.ConfirmPassword = Crypto.Encrypt(user.ConfirmPassword);
- user.ConfirmarEmail = false;
- user.IsEnabled = true;
- user.PerfilId = db.Perfils.Where(p => p.Name.Equals("Parceiro")).FirstOrDefault().PerfilId;
- user.CampanhaId = db.Campanhas.Where(c => c.Tipo.Equals("Cashback")).FirstOrDefault().CampanhasId;
- if (ModelState.IsValid)
- {
- var isExiste = UserHelper.EmailExiste(user.UserName);
- if (isExiste)
- {
- ModelState.AddModelError("", "");
- ViewBag.Message = "Email já possui cadastro em nosso sistema";
- return View(user);
- }
-
- db.Users.Add(user);
- await db.SaveChangesAsync();
- string callbackUrl = await SendEmailConfirmationTokenAsync(user.UserName, "Por favor, confirme seu e-mail", Convert.ToString(user.ActivationCode));
- ViewBag.Message = "Por favor, verifique seu e-mail antes de continuar.";
- return View("Info");
-
- }
- else
- {
- message = "Erro na Requisição";
- }
-
- ViewBag.Message = message;
- return View(user);
- }
-
-
-
-
- [AllowAnonymous]
- [HttpGet]
- public ActionResult VerifyAccount(string id)
- {
- bool Status = false;
-
- db.Configuration.ValidateOnSaveEnabled = false;
- var v = db.Users.Where(a => a.ActivationCode == new Guid(id)).FirstOrDefault();
- if (v != null)
- {
- v.ConfirmarEmail = true;
- db.SaveChanges();
- Status = true;
- }
- else
- {
- ViewBag.Message = "Requisição invalida";
- }
-
- ViewBag.Status = Status;
- return View();
- }
-
-
-
-
- [HttpGet]
- [AllowAnonymous]
- public ActionResult Login()
- {
-
- return View();
- }
-
-
-
-
- [HttpPost]
- [AllowAnonymous]
- [ValidateAntiForgeryToken]
- public async Task<ActionResult> Login(UserLogin login, string ReturnUrl = "")
- {
- string message = "";
- var user = db.Users.Where(a => a.UserName == login.UserName).FirstOrDefault();
- if (user != null)
- {
-
- if (user.ConfirmarEmail == false)
- {
- Guid activationcode = user.ActivationCode;
- string callbackUrl = await SendEmailConfirmationTokenAsync(user.UserName, "Confirmação de e-mail reenviada", activationcode.ToString());
- ViewBag.Message = "Por favor, verifique seu e-mail antes de realizar o login.";
- return View("Info");
-
-
- }
- else
- {
- if (user.IsEnabled == false)
- {
- return View("Lockout");
- }
- else
- {
-
- if (string.Compare(Crypto.Encrypt(login.Password), user.Password) == 0)
- {
-
-
-
-
-
-
-
-
-
-
- FormsAuthentication.SetAuthCookie(login.UserName, login.RememberMe);
-
-
- if (Url.IsLocalUrl(ReturnUrl))
- {
- return Redirect(ReturnUrl);
- }
- else
- {
- return RedirectToAction("Index", "Home");
- }
- }
- else
- {
- message = " E-mail e / ou senha incorreto(s).";
- }
- }
- }
- }
- else
- {
- message = " E-mail e / ou senha incorreto(s).";
- }
-
- ViewBag.Message = message;
- return View();
- }
-
-
-
-
- [AuthorizedAction]
- [HttpPost]
- public ActionResult Logout()
- {
- FormsAuthentication.SignOut();
- return RedirectToAction("Login", "Conta");
- }
-
-
-
- [NonAction]
- private async Task<string> SendEmailConfirmationTokenAsync(string userName, string subject, string activationCode, string emailFor = "VerifyAccount")
- {
- var verifyUrl = "/Conta/" + emailFor + "/" + activationCode;
- var callbackUrl = Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery, verifyUrl);
-
- if (emailFor == "VerifyAccount")
- {
- string body = macpartner.Resources.emailConfirmationBody;
- body = body.Replace("[link]", callbackUrl);
- await MailHelper.SendMail(userName, subject, body);
- }
- if (emailFor == "ResetPassword")
- {
- var body = macpartner.Resources.forgotPassBody;
- body = body.Replace("Oi[nome]", "Olá");
- body = body.Replace("[link]", callbackUrl);
- await MailHelper.SendMail(userName, subject, body);
- }
-
- return callbackUrl;
- }
-
-
-
- [AllowAnonymous]
- public ActionResult ForgotPassword()
- {
- return View();
- }
-
-
-
- [HttpPost]
- [AllowAnonymous]
- public async Task<ActionResult> ForgotPassword(ForgotPasswordModel model)
- {
- var account = db.Users.Where(a => a.UserName == model.Email).FirstOrDefault();
- string message = "";
-
- if (account != null)
- {
- string resetCode = Guid.NewGuid().ToString();
- await SendEmailConfirmationTokenAsync(account.UserName, "IndicaMais - Cadastro de Nova Senha", resetCode, "ResetPassword");
- account.ResetPasswordCode = resetCode;
- db.Configuration.ValidateOnSaveEnabled = false;
- db.SaveChanges();
-
- return RedirectToAction("ForgotPasswordConfirmation", "Conta");
- }
- else
- {
- message = "Usuário Não encontrado";
- }
-
- ViewBag.Message = message;
- return View(model);
- }
-
-
-
-
- [AllowAnonymous]
- public ActionResult ForgotPasswordConfirmation()
- {
- return View();
- }
-
-
-
- [AllowAnonymous]
- public ActionResult ResetPassword(string id)
- {
-
- if (string.IsNullOrWhiteSpace(id))
- {
- return HttpNotFound("Error");
- }
-
-
- var user = db.Users.Where(a => a.ResetPasswordCode == id).FirstOrDefault();
- if (user != null)
- {
- ResetPasswordModel model = new ResetPasswordModel();
- model.ResetCode = id;
- return View(model);
- }
- else
- {
- return HttpNotFound();
- }
-
- }
-
-
-
- [HttpPost]
- [AllowAnonymous]
- [ValidateAntiForgeryToken]
- public ActionResult ResetPassword(ResetPasswordModel model)
- {
- var message = "";
- if (ModelState.IsValid)
- {
-
- var user = db.Users.Where(a => a.ResetPasswordCode == model.ResetCode).FirstOrDefault();
- if (user != null)
- {
- user.Password = Crypto.Encrypt(model.Password);
- user.ConfirmPassword = Crypto.Encrypt(model.ConfirmPassword);
- user.ResetPasswordCode = "";
- db.Configuration.ValidateOnSaveEnabled = false;
- db.SaveChanges();
- return RedirectToAction("ResetPasswordConfirmation", "Conta");
- }
-
- }
- else
- {
- message = "Erro na requisição";
- }
- ViewBag.Message = message;
- return View(model);
- }
-
-
-
-
- [AllowAnonymous]
- public ActionResult ResetPasswordConfirmation()
- {
- return View();
- }
- }
- }
- <globalization culture="pt-BR" uiCulture="pt-BR" enableClientBasedCulture="true" />
- <customErrors mode="Off" />
- <authentication mode="Forms">
- <forms name=".User" cookieless="UseDeviceProfile" loginUrl="~/Conta/Login" path="/" timeout="5760" protection="All" slidingExpiration="true"></forms>
- <!--<forms name=".User" cookieless="UseDeviceProfile" loginUrl="~/Conta/Login" domain="indicamais.com.br" path="/" timeout="5760"></forms>-->
- </authentication>
- <sessionState sqlConnectionString="DefaultConnection" mode="InProc" sqlCommandTimeout="30"/>
We also use a class to encrypt user passwords
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text;
- using System.Web;
-
- namespace macpartner.Helpers
- {
- public static class Crypto
- {
- public static string Encrypt(string password)
- {
-
-
- if (password == null)
- {
- password = String.Empty;
- }
-
-
- var passwordBytes = Encoding.UTF8.GetBytes(password);
-
-
- passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
-
- var bytesEncrypted = Crypto.Encrypt(passwordBytes);
-
- return Convert.ToBase64String(bytesEncrypted);
- }
-
-
- public static string Decrypt(string password)
- {
-
- if (password == null)
- {
- password = String.Empty;
- }
-
-
-
- var passwordBytes = Encoding.UTF8.GetBytes(password);
-
- passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
-
- var bytesDecrypted = Crypto.Decrypt(passwordBytes);
-
- return Encoding.UTF8.GetString(bytesDecrypted);
- }
-
- private static byte[] Encrypt(byte[] passwordBytes)
- {
- byte[] encryptedBytes = null;
-
-
- var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
-
- using (MemoryStream ms = new MemoryStream())
- {
- using (RijndaelManaged AES = new RijndaelManaged())
- {
- var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
-
- AES.KeySize = 256;
- AES.BlockSize = 128;
- AES.Key = key.GetBytes(AES.KeySize / 8);
- AES.IV = key.GetBytes(AES.BlockSize / 8);
-
- AES.Mode = CipherMode.CBC;
-
- using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
- {
- cs.Write(passwordBytes, 0, passwordBytes.Length);
- cs.Close();
- }
-
- encryptedBytes = ms.ToArray();
- }
- }
-
- return encryptedBytes;
- }
-
- private static byte[] Decrypt(byte[] passwordBytes)
- {
- byte[] decryptedBytes = null;
-
- var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
-
- using (MemoryStream ms = new MemoryStream())
- {
- using (RijndaelManaged AES = new RijndaelManaged())
- {
- var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
-
- AES.KeySize = 256;
- AES.BlockSize = 128;
- AES.Key = key.GetBytes(AES.KeySize / 8);
- AES.IV = key.GetBytes(AES.BlockSize / 8);
- AES.Mode = CipherMode.CBC;
-
- using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
- {
- cs.Write(passwordBytes, 0, passwordBytes.Length);
-
- }
-
- decryptedBytes = ms.ToArray();
- }
- }
-
- return decryptedBytes;
- }
-
- }
- }