I have declared Session variable in "Global.asax" file as,
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
int temp=4;
HttpContext.Current.Session.Add("_SessionCompany",temp);
}
And want to use this Session Variable into My Controller's action as,
public ActionResult Index()
{
var test = this.Session["_SessionCompany"];
return View();
}
But I am Getting Exception While accessing the Session Variable.
Please help me on this that How can I access the Session Variable into my controller's Action.
I am getting an Exception like
"Object Reference not set to an Insatance of an object"
in Application_Start in Global.asax on line
HttpContext.Current.Session.Add("_SessionCompany",temp);
The thread that starts the Application is not the request thread used when the user makes a request to the web page.
That means when you set in the Application_Start, you're not setting it for any user.
You want to set the session on Session_Start event.
Edit:
Add a new event to your global.asax.cs file called Session_Start and remove the session related stuff from Application_Start
protected void Session_Start(Object sender, EventArgs e)
{
int temp = 4;
HttpContext.Current.Session.Add("_SessionCompany",temp);
}
This should fix your issue.
You should not set session variables in Application_Start(), as that method is only called once, when the application kicks off in IIS. It is not session based.
In addition, I assume your controller has a Session property? Have you set it correctly?
Use HttpContext.Current.Session["_SessionCompany"] rather than this.Session["_SessionCompany"] - that should work.
In controller, you can access like this..
YourControllerID.ControllerContext.HttpContext.Session["_SessionCompany"]
Use this helper class:
namespace Projectname.UI.HtmlHelpers
{
//[DebuggerNonUserCodeAttribute()]
public static class SessionHelper
{
public static T Get<T>(string index)
{
//this try-catch is done to avoid the issue where the report session is timing out and breaking the entire session on a refresh of the report
if (HttpContext.Current.Session == null)
{
var i = HttpContext.Current.Session.Count - 1;
while (i >= 0)
{
try
{
var obj = HttpContext.Current.Session[i];
if (obj != null && obj.GetType().ToString() == "Microsoft.Reporting.WebForms.ReportHierarchy")
HttpContext.Current.Session.RemoveAt(i);
}
catch (Exception)
{
HttpContext.Current.Session.RemoveAt(i);
}
i--;
}
if (!HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Equals("~/Home/Default"))
{
HttpContext.Current.Response.Redirect("~/Home/Default");
}
throw new System.ComponentModel.DataAnnotations.ValidationException(string.Format("You session has expired or you are currently logged out.", index));
}
try
{
if (HttpContext.Current.Session.Keys.Count > 0 && !HttpContext.Current.Session.Keys.Equals(index))
{
return (T)HttpContext.Current.Session[index];
}
else
{
var i = HttpContext.Current.Session.Count - 1;
while (i >= 0)
{
try
{
var obj = HttpContext.Current.Session[i];
if (obj != null && obj.GetType().ToString() == "Microsoft.Reporting.WebForms.ReportHierarchy")
HttpContext.Current.Session.RemoveAt(i);
}
catch (Exception)
{
HttpContext.Current.Session.RemoveAt(i);
}
i--;
}
if (!HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Equals("~/Home/Default"))
{
HttpContext.Current.Response.Redirect("~/Home/Default");
}
throw new System.ComponentModel.DataAnnotations.ValidationException(string.Format("You session does not contain {0} or has expired or you are currently logged out.", index));
}
}
catch (Exception e)
{
var i = HttpContext.Current.Session.Count - 1;
while (i >= 0)
{
try
{
var obj = HttpContext.Current.Session[i];
if (obj != null && obj.GetType().ToString() == "Microsoft.Reporting.WebForms.ReportHierarchy")
HttpContext.Current.Session.RemoveAt(i);
}
catch (Exception)
{
HttpContext.Current.Session.RemoveAt(i);
}
i--;
}
if (!HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Equals("~/Home/Default"))
{
HttpContext.Current.Response.Redirect("~/Home/Default");
}
return default(T);
}
}
public static void Set<T>(string index, T value)
{
HttpContext.Current.Session[index] = (T)value;
}
}
}
and in your controller you set everything e.g. a login controller:
Session Helper.Set<string>("Username", Login User.User Name);
Session Helper.Set<int?>("Tenant Id", Login User.Tenant Id);
SessionHelper.Set<User Type>("User Type");
SessionHelper.Set<string>("", Login User To String());
SessionHelper.Set<int>("Login User Id", Login User.Login UserId);
SessionHelper.Set<string>("Login User", Login User.To String());
SessionHelper.Set<string>("Tenant", Tenant);
SessionHelper.Set<string>("First name", Login User.First Name);
SessionHelper.Set<string>("Surname", Login User.Surname);
SessionHelper.Set<string>("Vendor ", Vendor );
SessionHelper.Set<string>("Wholesaler ", Wholesaler );
SessionHelper.Set<int?>("Vendor Id", Login User );
SessionHelper.Set<int?>("Wholesaler Id", Login User Wholesaler Id);
and you just call it anywhere you want:
var CreatedBy = SessionHelper.Get<int>("LoginUserId"),
it is a simple get to the the entity or set to assign it.
public ActionResult DeclareSession()
{
int id=3;
Session["User"]=id;
int iUserID =Convert.ToInt32(HttpContext.Current.Session["User"].toString());
return true;
}
Related
The context: An AspNetCore controller I've been asked to maintain contains methods similar to the following:
// Get api/Foo/ABCXXX/item/12345
[HttpGet("{accountId}/item/{itemNumber}")]
public async Task<ActionResult<ItemViewModel>> GetFoo([FromRoute] string accountId, [FromRoute] int itemNumber)
{
if (string.IsNullOrWhiteSpace(accountId))
{
return BadRequest("accountId must be provided");
}
if (itemNumber < 0)
{
return BadRequest("itemNumber must be positive");
}
if (!await CanAccessAccountAsync(accountId))
{
return Forbid();
}
// Returns null if account or item not found
var result = _fooService.GetItem(accountId, itemNumber);
if (result == null)
{
return NotFound();
}
return result;
}
// GET api/Foo/ABCXXX
[HttpGet("{accountId}")]
public async Task<ActionResult<IEnumerable<ItemViewModel>>> GetFoos([FromRoute] string accountId)
{
if (string.IsNullOrWhiteSpace(accountId))
{
return BadRequest("accountId must be provided");
}
if (!await CanAccessAccountAsync(accountId))
{
return Forbid();
}
// Returns null if account not found
var results = _fooService.GetItems(accountId);
if (results == null)
{
return NotFound();
}
return Ok(results);
}
You may assume that there are more than 2 such methods with very similar parts.
Looking at this code makes me itchy—there appears to be a lot of repetition, but the repeated parts can't be extracted to their own methods because they contain return statements.
To me, it would make sense for these early exits to be exceptions rather than return values. Say, for the sake of argument, that I define an exception to wrap an IActionResult:
internal class ActionResultException : Exception
{
public ActionResultException(IActionResult actionResult)
{
ActionResult = actionResult;
}
public IActionResult ActionResult { get; }
}
Then I can extract some specific validations:
private void CheckAccountId(string accountId)
{
if (string.IsNullOrWhiteSpace(accountId))
{
throw new ActionResultException(BadRequest("accountId must be provided"));
}
}
private async Task CheckAccountIdAccessAsync(string accountId)
{
if (!await CanAccessAccountAsync(accountId))
{
throw new ActionResultException(Forbid());
}
}
private void CheckItemNumber(int itemNumber)
{
if (itemNumber < 0)
{
throw new ActionResultException(BadRequest("itemNumber must be positive"));
}
}
And rewrite the controller to use them:
// Get api/Foo/ABCXXX/item/12345
[HttpGet("{accountId}/item/{itemNumber}")]
public async Task<IActionResult> GetFoo([FromRoute] string accountId, [FromRoute] int itemNumber)
{
try
{
CheckAccountId(accountId);
CheckItemNumber(itemNumber);
await CheckAccountIdAccessAsync(accountId);
// Returns null if account or item not found
var result = _fooService.GetItem(accountId, itemNumber);
if (result == null)
{
return NotFound();
}
return Ok(result);
}
catch (ActionResultException e)
{
return e.ActionResult;
}
}
// GET api/Foo/ABCXXX
[HttpGet("{accountId}")]
public async Task<IActionResult> GetFoos([FromRoute] string accountId)
{
try
{
CheckAccountId(accountId);
await CheckAccountIdAccessAsync(accountId);
// Returns null if account not found
var results = _fooService.GetItems(accountId);
if (results == null)
{
return NotFound();
}
return Ok(results);
}
catch (ActionResultException e)
{
return e.ActionResult;
}
}
To get this to work, I had to wrap the controller bodies in a try to unwrap the action result from the exception.
I also had to revert the return types to IActionResult—there are reasons I may prefer not to do that. The only thing I can think of to address that problem is to go more specific with the exceptions and catches, but this seems only to shift the WET-ness from the validation code to the catch blocks.
// Exceptions
internal class AccessDeniedException : Exception { ... }
internal class BadParameterException : Exception { ... }
// Controller
private void CheckAccountId(string accountId)
{
if (string.IsNullOrWhiteSpace(accountId))
{
throw new BadParameterException("accountId must be provided");
}
}
private async Task CheckAccountIdAccessAsync(string accountId)
{
if (!await CanAccessAccountAsync(accountId))
{
throw new AccessDeniedException();
}
}
private void CheckItemNumber(int itemNumber)
{
if (itemNumber < 0)
{
throw new BadParameterException("itemNumber must be positive");
}
}
// Get api/Foo/ABCXXX/item/12345
[HttpGet("{accountId}/item/{itemNumber}")]
public async Task<IActionResult> GetFoo([FromRoute] string accountId, [FromRoute] int itemNumber)
{
try
{
...
}
catch (AccessDeniedException)
{
return Forbid();
}
catch(BadParameterException e)
{
return BadRequest(e.Message);
}
}
// GET api/Foo/ABCXXX
[HttpGet("{accountId}")]
public async Task<IActionResult> GetFoos([FromRoute] string accountId)
{
try
{
...
}
catch (AccessDeniedException)
{
return Forbid();
}
catch (BadParameterException e)
{
return BadRequest(e.Message);
}
}
There's a few simple things you can do. No need to go overboard at this point.
First and foremost, checking whether accountId is null or whitespace is completely superfluous. It's part of the route; if something isn't stuck in there, you wouldn't get here in the first place.
Second, you can make judicious use of route constraints where appropriate. For example, for your itemNumber being positive:
[HttpGet("{accountId}/item/{itemNumber:min(0)}")]
Though, honestly, I'm not sure something like /XXXX/item/-1 would even work in the first place. Regardless, specifying a min value will cover you.
Third, your CanAccessAccount check should actually be handled via resource-based authorization, built-in to ASP.NET Core.
Long and short, if you use what's already available to you, you actually don't need to do much additional validation, in the first place, negating the need to find some way to "factor it out".
I am new to MVC. I searched and found no solution that fits for my requirements.
I am developing a web portal for our team's internal use which uses Windows AD authentication for login. However, for role based access I have created a local database which can return the Role details for the user.
I have created a custom Authorization filter that allows me to handle authorization based on the user's role. This filter is querying details from the DB however the issue with this approach is, it will try to get details from DB for every request to the controller which makes it expensive.
How can I save the user details fetched from the DB in a Token such that I don't have to query DB for every request and use the Token values inside the Authorization filter. Also, I can use the values retrieved for the user from the database, anywhere else in the app. (There are some other details for the user we have in the Database).
If someone can suggest a better way to achieve this, please help.
Here is the code that I am currently using inside Authorization filter:
public class AuthorizeRole : AuthorizeAttribute
{
private bool _authenticated;
private bool _authorized;
public string InRoles { get; set; }
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
if (_authenticated && !_authorized)
{
filterContext.Result = new RedirectResult("/account/error");
}
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
_authenticated = base.AuthorizeCore(httpContext);
if (_authenticated)
{
if (string.IsNullOrEmpty(InRoles))
{
_authorized = true;
return _authorized;
}
if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
{
string NTID = httpContext.User.Identity.Name.Split('\\')[1];
var roles = InRoles.Split(',');
using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
{
try
{
ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
var user = userResults.FirstOrDefault(all => all.NTID == NTID);
if (user == null)
{
_authorized = false;
return _authorized;
}
else
{
if (roles.Contains(user.Role))
{
return _authorized;
}
}
}
catch (Exception)
{
_authorized = false;
return _authorized;
}
}
}
else
{
_authorized = false;
return _authorized;
}
}
_authorized = false;
return _authorized;
}
}
Please suggest at which section to use the code you will be suggesting (like, inside controller, inside filter or somewhere else.)
I found this solution at: this site but there it is used for AD groups.
I have checked the cookie in override version of method AuthorizeCore it is working now:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = httpContext.Request.Cookies[cookieName];
_authenticated = base.AuthorizeCore(httpContext);
string authToken = httpContext.Request.Headers["Auth-Token"];
if (_authenticated)
{
if (authCookie == null)
{
if (string.IsNullOrEmpty(InRoles))
{
_authorized = true;
return _authorized;
}
if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
{
string NTID = httpContext.User.Identity.Name.Split('\\')[1];
var roles = InRoles.Split(',');
using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
{
try
{
ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
var user = userResults.FirstOrDefault(all => all.NTID == NTID);
if (user == null)
{
_authorized = false;
return _authorized;
}
else
{
if (roles.Contains(user.Role))
{
_authorized = true;
return _authorized;
}
}
}
catch (Exception)
{
_authorized = false;
return _authorized;
}
}
}
else
{
_authorized = false;
return _authorized;
}
}
}
_authorized = false;
return _authorized;
}
First off, you might want to look at using AD Security Groups to manage access. That way OPS can continue to maintain access in a familiar time-tested platform and you dont have to write your own security definition interface.
As for the MVC security persistence
All you have to do is add a manual log in to perform your above logic and then you use the built-in Membership Provider (for whatever version of MVC you are using) to log the user in. MVC will handle maintaining the logged in state and tokenising for you and you can specify things like timeout in the web.config (or settings.json in Core).
Sorry i dont have any sample code at hand for illustration.
I am creating an API that will enable CRUD functionality to Create, Read, Update, and Delete record in database.
I am running into an issue that is not allowing me to update entry inside a table due to an instance is shared and I get below error.
cannot be tracked because another instance of this type with the same key is already being tracked. For new entities consider using an IIdentityGenerator to generate unique key values."
Here is my code:
[HttpPut("{id}")]
public JsonResult Put(int Id, [FromBody]PackageVersion updatePackage)
{
try
{
if (ModelState.IsValid)
{
if (updatePackage == null || updatePackage.Id != Id)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { status = "Bad Request" });
}
var package = _respository.GetPackageById(Id);
if (package == null)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return Json(new { status = "Not Found", Message = package });
}
_respository.UpdatePackage(updatePackage);
if (_respository.SaveAll())
{
Response.StatusCode = (int)HttpStatusCode.Accepted;
return Json(updatePackage);
}
}
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { status = "Failed", ModelState = ModelState });
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { status = "Failed", Message = ex.Message });
}
}
In the above code you will notice I am first getting a record by using repository _repository.GetPackageById(Id), which allows me to validate that a record is in database and I can continue to update by using _repository.UpdatePackage(updatePackage) repository. If I comment out below code in my controller, I am able to save the data in the database.
//var package = _respository.GetPackageById(Id);
//if (package == null)
//{
// Response.StatusCode = (int)HttpStatusCode.NotFound;
// return Json(new { status = "Not Found", Message = package });
//}
I also made sure that I was using AddScoped in startup configuration as mentioned in this thread.
services.AddScoped<IAutomationRepository, AutomationRepository>();
I am not sure why I cant use multiple DBContext instances for same ID when it is called.
Any suggestion is really appreciated. :)
UPDATE 1:
public class AutomationRepository : IAutomationRepository
{
private AutomationDBContext _context;
public AutomationRepository(AutomationDBContext context)
{
_context = context;
}
public void AddPackage(PackageVersion newPackage)
{
_context.Add(newPackage);
}
public void DeletePackage(int id)
{
var package = _context.PackageVersions.SingleOrDefault(p => p.Id == id);
_context.PackageVersions.Remove(package);
}
public IEnumerable<PackageVersion> GetAllPackages()
{
return _context.PackageVersions.OrderBy(p => p.PackageName).ToList();
}
public object GetPackageById(int id)
{
return _context.PackageVersions.SingleOrDefault(p => p.Id == id);
}
public bool SaveAll()
{
return _context.SaveChanges() > 0;
}
public void UpdatePackage(PackageVersion updatePackage)
{
_context.Update(updatePackage);
}
Change your repository method like below. This may help. Let us know what happens
public object GetPackageById(int id)
{
return _context.PackageVersions.AsNoTracking().SingleOrDefault(p => p.Id ==id);
}
I've been looking at ServiceStack and I'm trying to understand how to use BasicAuthentication on a service with an existing database. I would like to generate a public key (username) and secret key (password) and put that in an existing user record. The user would then pass that to the ServiceStack endpoint along with their request.
What do I need to implement in the ServiceStack stack to get this working?
I have looked at both IUserAuthRepository and CredentialsAuthProvider base class and it looks like I should just implement IUserAuthRepository on top of my existing database tables.
I am also trying to figure out what is the bare minimum I should implement to get authentication working. I will not be using the service to Add or Update user access to the Service, but instead using a separate web application.
Any help and past experiences are greatly appreciated.
Example of authenticating against an existing database (in this case via Umbraco/ASP.NET membership system). 1) Create your AuthProvider (forgive the verbose code, and note you don't have to override TryAuthenticate too, this is done here to check if the user is a member of specific Umbraco application aliases):
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Security;
using ServiceStack.Configuration;
using ServiceStack.Logging;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.WebHost.Endpoints;
using umbraco.BusinessLogic;
using umbraco.providers;
public class UmbracoAuthProvider : CredentialsAuthProvider
{
public UmbracoAuthProvider(IResourceManager appSettings)
{
this.Provider = "umbraco";
}
private UmbracoAuthConfig AuthConfig
{
get
{
return EndpointHost.AppHost.TryResolve<UmbracoAuthConfig>();
}
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
ILog log = LogManager.GetLogger(this.GetType());
var membershipProvider = (UsersMembershipProvider)Membership.Providers["UsersMembershipProvider"];
if (membershipProvider == null)
{
log.Error("UmbracoAuthProvider.OnAuthenticated - NullReferenceException - UsersMembershipProvider");
session.IsAuthenticated = false;
return;
}
MembershipUser user = membershipProvider.GetUser(session.UserAuthName, false);
if (user == null)
{
log.ErrorFormat(
"UmbracoAuthProvider.OnAuthenticated - GetMembershipUser failed - {0}", session.UserAuthName);
session.IsAuthenticated = false;
return;
}
if (user.ProviderUserKey == null)
{
log.ErrorFormat(
"UmbracoAuthProvider.OnAuthenticated - ProviderUserKey failed - {0}", session.UserAuthName);
session.IsAuthenticated = false;
return;
}
User umbracoUser = User.GetUser((int)user.ProviderUserKey);
if (umbracoUser == null || umbracoUser.Disabled)
{
log.WarnFormat(
"UmbracoAuthProvider.OnAuthenticated - GetUmbracoUser failed - {0}", session.UserAuthName);
session.IsAuthenticated = false;
return;
}
session.UserAuthId = umbracoUser.Id.ToString(CultureInfo.InvariantCulture);
session.Email = umbracoUser.Email;
session.DisplayName = umbracoUser.Name;
session.IsAuthenticated = true;
session.Roles = new List<string>();
if (umbracoUser.UserType.Name == "Administrators")
{
session.Roles.Add(RoleNames.Admin);
}
authService.SaveSession(session);
base.OnAuthenticated(authService, session, tokens, authInfo);
}
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
ILog log = LogManager.GetLogger(this.GetType());
var membershipProvider = (UsersMembershipProvider)Membership.Providers["UsersMembershipProvider"];
if (membershipProvider == null)
{
log.Error("UmbracoAuthProvider.TryAuthenticate - NullReferenceException - UsersMembershipProvider");
return false;
}
if (!membershipProvider.ValidateUser(userName, password))
{
log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - ValidateUser failed - {0}", userName);
return false;
}
MembershipUser user = membershipProvider.GetUser(userName, false);
if (user == null)
{
log.ErrorFormat("UmbracoAuthProvider.TryAuthenticate - GetMembershipUser failed - {0}", userName);
return false;
}
if (user.ProviderUserKey == null)
{
log.ErrorFormat("UmbracoAuthProvider.TryAuthenticate - ProviderUserKey failed - {0}", userName);
return false;
}
User umbracoUser = User.GetUser((int)user.ProviderUserKey);
if (umbracoUser == null || umbracoUser.Disabled)
{
log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - GetUmbracoUser failed - {0}", userName);
return false;
}
if (umbracoUser.UserType.Name == "Administrators"
|| umbracoUser.GetApplications()
.Any(app => this.AuthConfig.AllowedApplicationAliases.Any(s => s == app.alias)))
{
return true;
}
log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - AllowedApplicationAliases failed - {0}", userName);
return false;
}
}
public class UmbracoAuthConfig
{
public UmbracoAuthConfig(IResourceManager appSettings)
{
this.AllowedApplicationAliases = appSettings.GetList("UmbracoAuthConfig.AllowedApplicationAliases").ToList();
}
public List<string> AllowedApplicationAliases { get; private set; }
}
2) Register provider via usual AppHost Configure method:
public override void Configure(Container container)
{
// .... some config code omitted....
var appSettings = new AppSettings();
AppConfig = new AppConfig(appSettings);
container.Register(AppConfig);
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
this.Plugins.Add(
new AuthFeature(
// using a custom AuthUserSession here as other checks performed here, e.g. validating Google Apps domain if oAuth enabled/plugged in.
() => new CustomAuthSession(),
new IAuthProvider[] { new UmbracoAuthProvider(appSettings)
}) {
HtmlRedirect = "/api/login"
});
}
3) Can now authenticate against existing Umbraco database # yourapidomain/auth/umbraco, using Umbraco to manage users/access to API. No need to implement extra user keys/secrets or BasicAuthentication, unless you really want to....
I'm just starting with ServiceStack and I needed exactly the same thing - and I managed to get it to work today.
The absolute bare minimum for logging in users via Basic Auth is this:
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
public class CustomBasicAuthProvider : BasicAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
// here, you can get the user data from your database instead
if (userName == "MyUser" && password == "123")
{
return true;
}
return false;
}
}
...and register it in the AppHost:
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new CustomBasicAuthProvider()
}) { HtmlRedirect = null });
That's all!
Another possible solution would be to use the default BasicAuthProvider and provide an own implementation of IUserAuthRepository instead.
I can show you an example of this as well, if you're interested.
EDIT:
Here's the bare minimum IUserAuthRepository - just inherit from InMemoryAuthRepository and override TryAuthenticate:
using ServiceStack.ServiceInterface.Auth;
public class CustomAuthRepository : InMemoryAuthRepository
{
public override bool TryAuthenticate(string userName, string password, out UserAuth userAuth)
{
userAuth = null;
if (userName == "MyUser" && password == "123")
{
userAuth = new UserAuth();
return true;
}
return false;
}
}
...and register it in the AppHost:
container.Register<IUserAuthRepository>(r => new CustomAuthRepository());
Of course, you need to register one of the default AuthProviders (Basic, Credentials, whatever) as well.
I want save users's IPs and activity in a table named logPublic,I want when a unAthenticated user try to access a speacial folder e.g Admin folder i can add a record in logpublic table that it have some fields for e,g : ID,IP,Activity,datetime .after that unathenticated user will be lock utomatically
I am use below code in Load_Page Event of masterpage in Admin folder:
$public partial class Admin : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
Session["IsBlocked"] = true;
string ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
HttpContext.Current.Session["UserIP"] = ip;
HttpContext.Current.Session["Activity"] = HttpContext.Current.Request.Url;
HttpContext.Current.Session["DateTime"] = System.DateTime.Now;
}
else
{
if(! HttpContext.Current.User.IsInRole("Admin"))
{
Session["BlockUser"] = true;
string ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
HttpContext.Current.Session["UserIP"] = ip;
}
}
}
}
$namespace StoreProject.Data
{
public class CustomSecurityModule :IHttpModule
{
storedbEntities StoreEnt = new storedbEntities();
public void Dispose()
{
throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
//throw new NotImplementedException();
context.BeginRequest += new EventHandler(this.app_DoSecuriy);
}
private void app_DoSecuriy(object sender, EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
storedbEntities StoreEnt = new storedbEntities();
if (context.Session["BlockUser"]!= null && Convert.ToBoolean(context.Session["BlockUser"])== true)
{
logPrivate Log = new logPrivate()
{
Username = context.User.Identity.Name,
IP = context.Session["UserIP"].ToString(),
Enter = System.DateTime.Now,
};
StoreEnt.logPrivates.AddObject(Log);
StoreEnt.SaveChanges();
context.Response.Redirect("~/UnAuthorizedAccess.aspx");
}
//ublock != null && bool.TryParse(ublock.ToString(),out isblocked) && isblocked
else if ( context.Session["BlockPublick"] != null
&& System.Convert.ToBoolean(context.Session["BlockPublick"]) == true)
{
LogPublic newLog = new LogPublic()
{
IP = context.Session["UserIP"].ToString(),
Activity = context.Session["Activity"].ToString(),
Enter = Convert.ToDateTime(context.Session["DateTime"])
};
StoreEnt.LogPublics.AddObject(newLog);
StoreEnt.SaveChanges();
context.Response.Redirect("~/UnAuthorizedAccess.aspx");
}
}
}
}
but when i run my application website ,i get an error from httpmodule :Object reference not set to an instance of an object. error in below line
if (context.Session["BlockUser"]!= null
&& Convert.ToBoolean(
context.Session["BlockUser"])== true)
i dont have any record in LogPublic table or logPrivate table when i want visit a page in Admin Folder
please guide me
thanks
Module's BeginRequest is too early to access the Session object as it hasn't been yet created by the ASP.NET Pipeline. You'd have to move your logic to one of later events in the processing pipeline (after PostAcquireRequestState)
http://msdn.microsoft.com/en-us/library/ms178473.aspx