I have a form called ObjectCollectionOuterForm which extends from sfForm. ObjectCollectionOuterForm is the main form of an embedded form, each embedded form has disabled its csrf with: $this->disableLocalCSRFProtection(), so now my form protection depends on the outer form but since it´s not a sfFormDoctrine dependent it has a field called _csrf_token but with no value inside. How can I generate it?
The CSRF protection is handled by sfForm class, it has nothing to do with sfFormDoctrine. The secret should get generated for you, but if you have problems you can pass it as a third argument to your form's constructor:
$form = new ObjectCollectionOuterForm($defaults, $options, $CSRFSecret);
Related
I've read that CSRF Tokens are automatically validated in Razor Pages but does this also apply to Controllers or do I still have to use the #Html.AntiForgeryToken() TagHelper in my view and the [ValidateAntiForgeryToken] attribute on my controller method?
If so, I've read on Andrew Locks Blog that I could add a Filter to do the same but this was before NetCore 3.+.
Is this implementation in my Startup.cs correct?
services.AddControllers()
.AddMvcOptions(options => {
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
No you do not need to use the #Html.AntiForgeryToken() because when you use the <form> tag helper it will insert the anti-forgery token for you (if the method attribute is "post" and the action is not an external hyperlink).
https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.1#aspnet-core-antiforgery-configuration
In ASP.NET Core 2.0 or later, the FormTagHelper injects antiforgery tokens into HTML form elements.
And:
The automatic generation of antiforgery tokens for HTML form elements happens when the tag contains the method="post" attribute and either of the following are true:
The action attribute is empty (action="").
The action attribute isn't supplied ().
Also:
We recommend use of AutoValidateAntiforgeryToken broadly for non-API scenarios. This ensures POST actions are protected by default. The alternative is to ignore antiforgery tokens by default, unless ValidateAntiForgeryToken is applied to individual action methods.
I need to add a field to the CAS 6.0.X login screen (language selector) that is not used to authenticate users but I need it after logging in.
How can I do to pass this field added to the form to the data that is passed to the client application in the "principal" object.
In the end I have achieved what I needed. We have overwritten the jdbc support module to add checks and there I have put the following code that helps me to retrieve parameters of the request.
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes()).getRequest();
String[] fields = fieldsToPrincipal.split(",");
for(String field : fields2Principal)
{
dbFields.put( field.trim() , request.getParameter( field.trim() ) );
}
fieldsToPrincipal It is a string of form field names that I want to send the applications through the "principal" map attributes.
Now in the properties files I have 2 properties in which I report the names of the fields. The default property that tells you which fields will be retrieved for the principal and my custom property where I indicate which fields will come from the form
cas.authn.jdbc.query[0].principalAttributeList:USERID, USERNAME, LANGUAGE_SELECTED
cas.custom.properties.jdbc.loginfields.to.principal=LANGUAGE_SELECTED
What I'm trying to achieve is to customise what happens during the HttpPost/OnSubmit of a form created with Umbraco Forms, whilst still maintaining the default behaviour of the form and any subsequent workflow.
In my specific scenario, I need to be able to analyse the input of the form and based on that input I will send the user to a different "thank you" page, whilst also storing some elements of the originally submitted form in TempData.
I've tried the following:
I've tried to create a DocType controller (RenderMvcController), but this only allows you
to override the HttpGet, and not Post.
I cannot use a SurfaceController as I lose the functionality of the
module, Umbraco Forms.
I've tried to use a custom workflow, but this runs asynchronous to
the user's journey and I cannot change their experience.
There isn't much useful documentation available for this at all and I'm finding this task more difficult than I expected it to be.
In order to add a custom procedure after the submission of the form, and based on this procedure change the user journey you must do the following:
Create a new controller and inherit from UmbracoFormsController and override the OnFormHandled method
public class CustomUmbracoFormsController : UmbracoFormsController
{
protected override void OnFormHandled(Form form, FormViewModel model)
{
// Find the field in the form, then search for a matching value
var field = form.AllFields.FirstOrDefault(x => x.Alias == "deliveryOptions");
var fieldValue = model.FormState[field.Id.ToString()].GetValue(0).ToString();
// Add the value to the TempData
TempData["deliveryOptions"] = fieldValue;
}
}
The above is a basic implementation that doesn't account for NULL
Update the reference to UmbracoFormsController in /Views/Partials/Forms/Form.cshtml with your new controller from above.
...
#using (Html.BeginUmbracoForm<CustomUmbracoFormsController>("HandleForm"))
...
In the above example we analyse the form data and store some information in the TempData, we can set the form to redirect to a generic thank you page in which we can analyse the values in the TempData and change the view the user sees.
Also, if you are making changes to the Form values and what these to be updated, you'll need the Record Guid, which you can retrieve from TempData["Forms_Current_Record_id"] in conjunction with a new RecordStore object.
We have a ViewModel for "create" and one for "edit." The edit inherits from create so that we're sharing common fields. We are then using an #Html.EditorForModel("User") that uses the "create" as its model.
This is for editing users, so I need the password field to be required on create, but not required on delete. Thus, the create VM has Password with [Required] decorating it, while the edit VM has password property with no decoration, and is also declared with new (public new string Password {get;set;}).
This is almost exactly similar to this question:
MVC4 Conditional Required Annotation
For my situation, it's still requiring the field I believe due to the EditorTemplate using the create object as its model instead of the edit. I tried changing it from editorformodel to:
#Html.EditorFor(model=>model, "User")
in hopes that because edit is actually a "create" due to inheritance that it would work, but it'still barking at me for not providing the required field when I post.
Is there a way to accomplish what I'm attempting, or are my options to either remove the required and handle it server-side, or split the editor template into two templates?
You can create a custom attribute to drive your check on whether the password is required or not. When the submission happens to the server your custom attribute can check to see if the you are dealing with an Update or and Insert and then invalidate the model if it needs to.
Here are some resources on creating custom attributes and custom attributes with unobstrusive jquery validation
Happy Coding!!
As I read the anti-forgery system that ASP.NET MVC implements generate a token that can be reused across the same session, my question is why then this token changes every time I generate a new form in my app? I am talking about the hidden input field, not about the cookie value.
Thanks.
No. the token is not reused.
Every page refresh will generate a new value in Form input (and Cookie as well, in case it is invalid or not exist). upon submission, the server will try to match the form value against the Cookie value.
Taken from Professional ASP.NET.MVC 3 book
Token Verifi cation ASP.NET MVC includes a nice way of preventing CSRF
attacks, and it works on the principle of verifying that the user who
submitted the data to your site did so willingly. The simplest way to
do this is to embed a hidden input into each form request that
contains a unique value. You can do this with the HTML Helpers by
including this in every form:
<form action=”/account/register”
> method=”post”> <#Html.AntiForgeryToken()> … </form>
Html.AntiForgeryToken will output an encrypted value as a hidden
input: This value
will match another value that is stored as a session cookie in the
user’s browser. When the form is posted, these values will be matched
using an ActionFilter:
[ValidateAntiforgeryToken] public ActionResult
> Register(…)