I have a ShopController and an Action method that I call CheckOut. I have [Authorize] before the the Action method, but what if I want the user to continue , after a successfull log in, to another Controller like the CustomersController and the Create View so that the customer can add address and other info into a form?
One option would could be to create a new View with a form within the ShopController, but I guess that isn't a good option!?
One option would could be to create a new View with a form within the
ShopController, but I guess that isn't a good option!?
No. This is the way you want to do it. Create action methods/controllers for different functional/logical pieces of your application. In this case, reading the address is a separate functionality and hence should belong to a separate controller-action method.
You may create a new CustomerController and add a CreateAddress action method ( and view) in that and in your action method which authenticates the user(Login?), use RedirectToAction method to send the user your new view as needed.
public ActionResult Login(string userName,string password)
{
// do your credential verification logic here
return RedirectToAction("CreateAddress","CustomerController");
}
Related
I followed the symfony 4 documentation to make a login form (https://symfony.com/doc/current/security/form_login_setup.html) and I added a registration form in the same controller.
I'm a beginner, and I would like to make an account page where the user will be able to change his informations, but I would like to know if I should create a new Controller who work with the user entity, on just work onthe same controller than the login and registration ?
Or maybe my user controller have to inherit the securityController?
I'm a noob, sorry ^^'
Thank you
You can give a look at https://symfony.com/doc/current/service_container.html#creating-configuring-services-in-the-container
The path is creating your own service(s), for example App\Servie\UserManager that performs every task on a User object
For example, you could have:
App\Service\UserManager
class UserManager
{
// ...
public function handleUpdatePasswordRequest(Request $request) {...}
// or
public function handleUpdatePasswordForm(Form $form) {...}
// or:
public function handleUpdatePassword(User $user, $newPlainPassword) {...}
...
}
as to say, whatever you want to implement, keeping in mind that the thinner the controllers are better it is, while services can grow (and be split) indefinitely
In my controllers, I have code like [Authorize(Roles = "Administrators")] annotated above some actions, and I want to know how AuthorizeAttribute uses the Roles parameter (the implementation of the checking mechanism). My goal is to create an extension of this class, called PrivilegeAttribute for example, so that I can annotate actions like [Privilege(Privileges = "read")]. In this class, I would check if the Role of the user has at least one of the privileges in this custom filter (read in this example). I have already created the association between roles and privileges in the code and in the database, and what I want help with is checking whether the role is associated to the privilege.
I tried seeing if that information is there in HttpContextBase.User.Identity but I couldn't find it.
Thank you.
If you don't need your own custom attribute and could live with using someone else attribute, than I would suggest to use the package Thinktecture.IdentityModel.Owin.ResourceAuthorization.Mvc as described here
Blog Post by Dominick Baier
and here
Git Hub Sample Code for the Package
so it basically works like this:
you put an attribute over your action like this:
[ResourceAuthorize("View", "Customer")]
The first argument is the name of the Action to check, the second one is the name of the attribute.
Then you derive from ResourceAuthorizationManager in your code and override the CheckAccessAssync Method
public class MyAuthorization : ResourceAuthorizationManager
{
public override Task<bool> CheckAccessAsync(ResourceAuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
// getting the roles that are connected to that resource and action
// from the db. Context could of course be injected into the
// constructor of the class. In my code I assume that the table
// thank links roles, resources and actions is called Roles ToActions
using(var db = MyContext())
var roles = db.RolesToActions // Use your table name here
.Where(r => r.Resource == resource && r.Action == action).ToList();
foreach(var role in roles)
{
if(context.Principal.IsInRole(role.Name)
{
return Ok();
}
}
return Nok();
}
}
}
So I hope this helps. If you prefer to implement your own attribute however, than the source code from the ResourceAuthorization GitHub Repository should be a good starting point
I'm new to ASP.Net MVC. In PHP, I always use the PRG pattern even when the post request was invalid. It was pretty easy with session flashes (also user friendly).
In ASP.Net MVC, however, I don't see an easy way to do PRG when the request is invalid. I could think of some ways, but I don't think they are good practices and put some extra unnecessary work.
Moreover, from a couple of articles that I've read, a PRG when the request was invalid was discouraged. If it's a bad practice, then what's the better way to handle unsuccessful post requests? Is it really better off without the PRG? And should I just let the rather annoying browser warnings when a user tries to refresh the page?
In Mvc, it's normal practice to handle your Post Actions as it follows:
[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult LoginForm(LoginViewModel loginViewModel)
{
if (!ModelState.IsValid)
return View("Login", loginViewModel);
return Redirect("/");
}
As you can see, the property ModelState.IsValid will tell you if the request is invalid, therefore giving you the ability to return the same view and display the error messages in the ValidationSummary when the Post request contains an error. This is the code for the View:
#using (Html.BeginForm("LoginForm", "Account"}))
{
#Html.ValidationSummary() // THIS WILL SHOW THE ERROR MESSAGES
#Html.AntiForgeryToken()
#Html.TextBoxFor(x => x.Email)
#Html.PasswordFor(x => x.Password)
<button type="submit">Submit</button>
}
We have been using PRG pattern in our asp.net mvc web apps for about 5 years. The main reason we adopted PRG was to support browser navigation (eg back, forward). Our web apps are used by customer and for front/back office operations. Our typical web page flow is starts with a login, then progresses via many list/detail view. We also incorporate partial views which also have their own viewmodel. List views will have links (GETS) for navigation. Detail views will have forms (POSTS) for navigation.
Keys aspects of our PRG:
We incorporate viewmodels so each view has a viewmodel (all data access is done in the viewmodel).
Each viewmodel has a set() & get() method to maintain the key data field values associated with the most recent instance of the view. The set/get values are persisted in sessionstate.
The set method has a parameter for each value that needs to be set. The get method is just called from the viewmodel constructor to populate the viewmodel's public "key" values.
The viewmodel will also have a public load() method that get all neccessary data for its view.
Our PRG pattern overview:
In controllers we have a separate GET method and a POST method for each action. The GET only displays a view; the POST processes the posted data.
For list (menu) views, the controller GET method calls the target view's set('item key values here') method, then invokes a RedirectToAction to to the target view's controller GET action.
The controller GET method will instantiate the viewmodel (thus causing get of set values), call its load method which uses the set/get key values to get it data, and returns the view/viewmodel.
The controller POST method will either have the viewmodel save the valid posted data then redirect to the next desired page (probably the previous list menu) -OR- if redisplay the current view if the data is invalid.
I have not documented all the PRG flow senarios that we implemented, but the above is the basic flow.
SAMPLE VIEWMODEL SET/GET METHODS
private void GetKeys() {
Hashtable viewModelKeys;
if (SdsuSessionState.Exists("RosterDetail"))
{
viewModelKeys = (Hashtable)SdsuSessionState.Get("RosterDetail");
EventId = (int)viewModelKeys["EventId"];
SessionNo = (int)viewModelKeys["SessionNo"];
viewModelKeys = null;
}
}
public static void SetKeys(int eventId, int sessionNo) {
Hashtable viewModelKeys = new Hashtable();
viewModelKeys.Add("EventId",eventId);
viewModelKeys.Add("SessionNo",sessionNo);
SdsuSessionState.Set("RosterDetail",viewModelKeys);
viewModelKeys = null;
}
SAMPLE CONTROLLER
[AcceptVerbs("Get")]
public ActionResult MenuLink(int eventId, int sessionNo, string submitButton) {
if (submitButton == RosterMenu.Button.PrintPreview) {
// P-R-G: set called viewmodel keys.
RosterDetail.SetKeys(eventId,sessionNo);
// Display page.
return RedirectToAction("Detail","Roster");
}
if (submitButton == RosterMenu.Button.Export) { etc ...}
}
I have a question on Spring MVC. I have a form where I take some values from user. And then on submit call action (say addTaskAction). It calls the controller below. The controller does what it needs to do (add Task to database) and calls the view showTasks. Till now,everything is fine. But here is my problem. The URL still shows /addTaskAction. So if I do a refresh or F5, the controller is again called and another task is added to database.
What is the cleanest/industry standard way of avoiding this? How to make sure that post form submit the URL shows /showTasks and not /addTaskAction.
...
Add
#RequestMapping(value = "/addTaskAction", method = RequestMethod.POST)
public String addTaskAction(#RequestParam("issueType") String issueType,
#RequestParam("priority") String priority,
#RequestParam("summary") String summary,
#RequestParam("reporter") String reporter,
#RequestParam("assignee") String assignee,
#RequestParam("status") String status,
#RequestParam("comments") String comments,
Model model) {
System.out.println(issueType);
Task task = new Task(issueType,priority,summary, reporter,
assignee,status,comments);
taskRepository.save(task);
model.addAttribute("tasks", taskRepository.getAllTasks());
//model.addAttribute("task", task);
System.out.println("Tasks added-"+taskRepository.getAllTasks().size());
return "showTasks";
}
You're not supposed to return a page from a POST, you're supposed to redirect to a different page, thus changing the url. In your example, you should probably have something like this:
return "redirect:showTasks";
This returns a redirect instruction to the browser, that then requests the page you've specified.
Since we have separation of layers it should be easier to isolate each layer by security. How does MVC in ASP.NET exploit this to more easily secure a website compared to using a webform?
By security I do not only mean authorization but also anti-hacking security.
1) Decorate Controller/Action by [Authorize] attribute (optionnaly with list of roles that allowed).
Example:
[Authorize("Manager")]
public class MyController:Controller
{
//Each action available only for authorized user
[Authorize(Roles = "Admin;Customer")]
public ActionResult MyAction()
{
//This action is available to the user that have a Manager role and one of next roles: Admin, Customer.
}
public ActionResult AnotherAction()
{
// This action is available for managers only.
}
}
2) Create area at your MVC project, create base controller, that decorated by authorize attribute, and make all controllers at area inherited from decorated controller - that's way you can easy implement admin area for website, for example.
Example:
[Authorize(Roles = "Admin")]
public class BaseController: Controller
{
}
public class My2Controller: BaseController
{
public ActionResult DoSomething()
{
//This action is available only for Admin.
}
}
If you need to protect site from HTML/script injection (user input ... at text field 'surname', that will collect data from admin page 'all site users' and post to his site when you open your page) - you can use next methods.
do nothing - by default MVC validates input, and don't process requests with HTML tags and returns error
use validation - for many kinds of data (names, phones, dates) user should not have possibility to use '<' and '>'. but you don't want user see error page if makes accidental mistake. Than enable client validation.
Use attribute [ValidateInput(false)] and encode incoming data - but user can't input HTML if he really need it.
If you really need user can format his message - use HTML filters for giving possibility input tags from list of permitted. As example: http://htmlagilitypack.codeplex.com/
Provide your own formatting dialect that will be safe and will not use HTML tags
If you need to protect from cross site fake form posting - use [ValidateAntiForgeryToken] attribute with #Html.AntiForgeryToken(); inside your <form> tag. This method generates hidden input with random value and cookie with known key and same value, and attribute check if form contains value, cookie contains value and form value equals to cookies value.
You can create your own security rules, using a bunch of attribute and hidden input on form: for example to set form time-outs.
You can put authorize attributed on each function call with role requirements.
One way users can hack your site is through "Cross-Site Request Forgery" and you can help prevent it by using AntiForgeryToken().
// Your View
#using (Html.BeginForm("Register", "Account"))
{
// Your Form Fields
#Html.AntiForgeryToken("someSalt")
}
// Your Controller
[HttpPost, ValidateAntiForgeryToken(Salt = "someSalt")]
public ActionResult Register(MyViewModel viewModel)
{
// Your Code
}