The Cross Site Scripting Cheat Sheet has many rules for securing against XSS attacks. I would like to implement those suggestions in my web app which is using Spring MVC + Jackson + JPA + Hibernate Bean Validation. As an example consider the following code that is similar to what I have in my app.
public class MessageJson {
#NotEmpty // Bean Validation annotation
private String title;
#NotEmpty
private String body;
// ... etc getters / setters
}
public class BolgPostController
{
#RequestMapping(value="messages",method=RequestMethod.POST)
public void createMessage(#Valid #RequestBody MessageJson message)
{
// **Question** How do I check that the message title and body don't contain
// nasty javascripts and other junk that should not be there?
// Call services to write data to the datababse
}
#RequestMapping(value="messages",method=RequestMethod.get)
public #ResponseBody List<MessageJson> createMessage()
{
// get data from the database
// **Question** How do I escape all the data in the list of MessageJson before
I send it back to the data.
}
}
I can see the following ways to implement the cheat sheet rules:
Option A Implement them manually in each controller method.
Option B Configure some extension to Spring MVC that can do it for me automatically
Option C Configure Jackson so that it can do it for me since most of my input/output goes through Jackson
I am looking for some example configurations of SpringMVC in any of those three options, with a preference for option B and C.
That would be easiest to do in setters for properties (like setTitle() for title property), when reading JSON.
Or if you are thinking of escaping additional characters (to, say, prevent embedding of HTML markup), have a look at this blog entry: escaping HTML characters in JSON with Jackson.
Related
What the difference between [FromRoute] and [FromBody] in a Web API?
[Route("api/Settings")]
public class BandwidthController : Controller
{
// GET: api/Settings
[HttpGet]
public IEnumerable<Setting> GetSettings()
{
return _settingRespository.GetAllSettings();
}
// GET: api/Settings/1
[HttpGet("{facilityId}", Name = "GetTotalBandwidth")]
public IActionResult GetTotalBandwidth([FromRoute] int facilityId)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
}
}
Also for PUT:
// PUT: api/Setting/163/10
[HttpPut]
public void UpdateBandwidthChangeHangup([FromRoute] int facilityId, int bandwidthChange)
{
_settingRespository.UpdateBandwidthHangup(facilityId, bandwidthChange);
}
Can I use [FromBody]?
FromBody
Specifies that a parameter or property should be bound using the request body.
When you use FromBody attribute you are specifying that the data is coming from the body of the request body and not from the request URL/URI. You cannot use this attribute with HttpGet requests, only with PUT,POST,and Delete requests. Also you can only use one FromBody attribute tag per action method in Web API (if this has changed in mvc core I could not find anything to support that).
FromRouteAttribute
Summary: Specifies that a parameter or property should be bound using route-data from the current request.
Essentially it FromRoute will look at your route parameters and extract / bind the data based on that. As the route, when called externally, is usually based on the URL. In previous version(s) of web api this is comparable to FromUri.
[HttpGet("{facilityId}", Name = "GetTotalBandwidth")]
public IActionResult GetTotalBandwidth([FromRoute] int facilityId)
So this would try to bind facilityId based on the route parameter with the same name.
Complete route definition: /api/Settings/GetTotalBandwidth/{facilityId}
Complete received url: /api/Settings/GetTotalBandwidth/100
Edit
Based on your last question, here is the corresponding code assuming you want 163 to be bound to facilityId and 10 to bandwidthChange parameters.
// PUT: api/Setting/163/10
[HttpPut("{facilityId}/{bandwidthChange}")] // constructor takes a template as parameter
public void UpdateBandwidthChangeHangup([FromRoute] int facilityId, [FromRoute] int bandwidthChange) // use multiple FromRoute attributes, one for each parameter you are expecting to be bound from the routing data
{
_settingRespository.UpdateBandwidthHangup(facilityId, bandwidthChange);
}
If you had a complex object in one of the parameters and you wanted to send this as the body of the Http Request then you could use FromBody instead of FromRoute on that parameter. Here is an example taken from the Building Your First Web API with ASP.NET Core MVC
[HttpPut("{id}")]
public IActionResult Update([FromRoute] string id, [FromBody] TodoItem item);
There are also other options in MVC Core like FromHeader and FromForm and FromQuery.
Confusion with [FromRoute] versus [FromBody]
Microsoft has done a good job with ASP.NET trying to connect Internet technology into their frameworks and systems. But in the process they often confuse developers by trying to patch their technology solutions on top of what are very simple HTTP and HTML technologies. People walk away assuming their solutions represent how the World Wide Web works...when it simply does not. Routing URL solutions in both their .NET Framework and Core version of ASP.NET are still confusing to many.
Hopefully this helps...
When you create a basic "route" in ASP.NET Core, you are binding your your browser's URL Address Path to a specific Controller Class and its child Method() inside a ASP.NET compiled application. Binding means that Middleware, they designed, sniffs the URL address and tries to take it apart and then match the pieces to code inside your website.
Special Controller-ControllerBase classes handle this process inside ASP.NET using Conventional Routing Templates and Routing Attributes mapped to child Methods inside your classes. That includes the parameters of those methods. This then "routes" all URL browser address path requests to a specific set of code inside your web application in ASP.NET.
Unfortunately, there are too many ways to configure this binding. In the past, it was a bunch of random combinations of Route Templates to controllers & methods, with additional code to map a url to parameters. But that was not always clear for things like query strings. ASP.NET Core has tried to clean up that mess with these new Attribute Routing decorations like [FromRoute], etc.
So how do they work?
[Route("/mypath/{myid}"]
public string MyMethod(int myid){...}
The above matches this browser URL address on the Web:
http://example.com/mypath/5
In its simplest form, ASP.NET MVC or WebAPI uses a "route" text string to map a specific method parameter name to a matching URL path. [FromRoute] helps by binding explicitly a methods parameter name to a matching part of the URL in {}:
[Route("api/[controller]")]// "/api/test"
public class TestController : ControllerBase
{
[HttpGet("{facilityId}")]// "/api/test/26"
public IActionResult GetTotalBandwidth([FromRoute] int facilityId)
{
...
}
}
The [FromRoute] attribute decoration, however, is optional as Middleware in ASP.NET by default tries to map that for you out of the box. If you leave [FromRoute] off, it will try and map your parameter name to the route template name inside {}, as so:
[Route("api/[controller]")]// "/api/test"
public class TestController : ControllerBase
{
[HttpGet("{facilityId}")]// "/api/test/26"
public IActionResult GetTotalBandwidth(int facilityId)
{
...
}
}
[FromQuery], however, only binds to Querystring URL parameters, which lie outside the URL route, according to Microsoft. But I have always considered them as part of the URL. In past iterations of ASP.NET this was left out so people had to fudge a way to grab these values inside the method using Request.QueryString. So this new feature fixes this issue:
[Route("api/[controller]")]// "/api/test"
public class TestController : ControllerBase
{
[HttpGet("{facilityId}")]// "/api/test/26?num=5"
public IActionResult GetTotalBandwidth(int facilityId,[FromQuery] int num)
{
...
}
}
[FromBody] is Completely Different!
Capturing data from a POST has always been tricky. ASP.NET helps solve that by allowing the route URL mapping system to function as normal in listening for the POST and URL request, but using an additional method parameter attribute system to bind to that data coming in using [FromBody]. In the case of POST HTTP VERB types, POST is unique, as a POST has nothing to do with URL mapping. But in this case ASP.NET is using the attribute parameter binding system to grab that form field data for you.
Let's first see how POST form fields work.
When you send HTML form data using a "method=post" like so:
<!doctype html>
<html xml:lang="en-us" lang="en-us">
<head></head>
<body>
<form id="f1" name="f1" method="post" action="">
<input type="text" id="field1" name="field1" size="20" value="" />
<button id="mybutton" name="mybutton" value="submit">Submit</button>
</form>
</body>
</html>
...that sends the form field data packaged inside the "body" of the Request like so as a POST:
HTTP HEADER
Content-Type: text/html
Last-Modified: Fri, 27 Jan 2023 17:45:32 GMT
HTTP BODY
field1=hello&mybutton=submit
Notice the form field POST data is inside a special "body" or payload section of the request post (field1=hello&mybutton=submit). To get that data, you need to use [FromForm](for traditional name-value form POST data) or [FromBody] (special JavaScript JSON Post data only) in ASP.NET parameter decorations, like so:
// Note: In the example below, "field1" only captures one field.
[Route("api/[controller]")]// "/api/test"
public class TestController : ControllerBase
{
[HttpPost]// "/api/test"
public string MyPostMethod([FromForm] string field1)
{
...
}
}
[FromForm] captures regular HTML POST form fields (one field or all fields) as name-value pairs in the WebAPI POST endpoint.
[FromBody] captures the form fields but only as JSON data, requiring an additional content-type of 'application/json' added to the POST request sent to the server. Because HTML Forms cannot do that, you have to use JavaScript when using [FromBody].
So, [FromBody] is almost always used with a POST and has nothing to do with binding a Route Template as part of the URL like [FromRoute] or [FromQuery] might do, but simply captures any POST data typically found inside a POST request form submission sent inside the Http Request package.
Hope that helps!
I am using Spring MVC for my Web Application and I need to turn a flash attribute into a permanent atribute so that if the user reloads the page it doesnt expire.
My controller looks like this
#RequestMapping(value="/verResultados/{id}")
public String irAVerResultados(#PathVariable Long id, RedirectAttributes redir)
{
redir.addFlashAttribute("encuestaSeleccionada", encuestasRepository.findOne(id));
return "redirect:/verResultados";
}
#RequestMapping(value="verResultados")
public String verResultados(#ModelAttribute("encuestaSeleccionada") Encuesta encuesta, Model model)
{
model.addAttribute("encuestaSeleccionada", encuesta); // This doesnt work.
return "verResultados";
}
How can I do it?
model.addAttribute is like request.setAttribute, so it is a flash attribute. in order to make a data permanent, i think you should use session. bit dirty, though
Is it possible to change a parameter name of an asmx web service without breaking clients? For example, consider a legacy service which has a web method like so:
[WebMethod]
public string HelloWorld(string NAME)
{
return "Hello World and " + NAME;
}
The legacy service web method has the parameter NAME, but I'd like to change this to 'Name' to follow coding guide-lines. Will this break existing clients?
The simplest might be to add a new method
//New clients use this Maybe you put it in a new asmx file.
[WebMethod]
public string Hello_World(string FullName)
{
return HelloWorld(FullName);
}
//Old clients use this.
[WebMethod]
public string HelloWorld(string NAME)
{
return "Hello World and " + NAME;
}
WCF has ways of having a Method name and parameter be one thing, but the xml be another using annotations. I think there is a way to create a WCF service that can talk to legacy ASMX clients, I haven't tried it. In that scenario you could rename all your methods and parameters and via attribute annotations, maintain the old names for the xml across the wire.
I have a form where I have two fields that I can add as much as I can. Think of it as like the upload file in gmail where I can add 1,2,3... files to upload only that I have two fields.
I am not so sure how this will check out using a SimpleFormController in Spring. Will the Spring Controller bind the them automatically?
My command class looks like this:
public class Course {
private long ID;
private String Owner;
private String Title;
private String Learning Objective;
//I am not so sure how this will be bound
private List<LearningActivity> learningActivities;
//accessor methods
}
public class LearningActivity {
private String Description;
private String link;
//accessor methods
}
I would suggest you to use Annotation-based Spring controllers as SimpleFormController is deprecated as of spring 3.0
If you are using annotations based
controller then their is no need to
extend any class or implement any
interface. The only thing you need to
do to make your simple java class to
become a Spring controller is to add
the #Controller annotation to it.
Example here
Also for handling dynamic fields in the form, it is better that you use Spring Form Tags
Example here
Edit: check 5.4.2.1. Registering additional custom PropertyEditors in spring docs, it has an example of what u want
i'm trying to work out the best method to perform logging in the application i'm currently developing.
right now, i have a Log table that stores the username, timestamp, action, controller, and a message. when a controller is instantiated, it gets the IoC info through Castle Windsor.
for example, my "Sites" controller is created as follows:
private ISitesRepository siteRepository;
private ILogWriter logWriter;
public SiteController(ISitesRepository siteRepository, ILogWriter logWriter)
{
this.siteRepository = siteRepository;
this.logWriter = logWriter;
}
and the log writer has a function that creates and inserts a log entry (WriteToLog). within the Sites controller's Edit and Create actions, it calls the WriteToLog function.
this is working and doing its job, but my question is- do i really need to set up each controller this way, passing through the ILogWriter interface/repository? it struck me that i could possibly set up a LogController, and just have that do the "heavy lifting" of writing to my logs.
that way, i wouldn't have to mess with the IoC stuff in every other controller. is it possible to execute an action on another controller (for example, a LogController-> WriteLog)? i'm not sure how would that be done without doing a redirect...
Could you pass by an abstract class? This abstract class having a static property referencing you log writer?
something like this
public abstract class BaseController
{
public static ILogWriter Logwriter{get;set;}
public static BaseController
{
Logwriter = YourFactory.GetLogwriter();
}
}
public class YourController:BaseController
{
public YourController(ISitesRepository siteRepository)
{
}
}
Ok, after much head scratching, i think i found an acceptable solution.
I implemented my logging action as a custom action filter as so:
public class LogAction : ActionFilterAttribute, IActionFilter
{
public LogLevel loglevel;
public string message;
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
logWriter.WriteToLog(
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
filterContext.ActionDescriptor.ActionName,
loglevel,
filterContext.HttpContext.Timestamp,
filterContext.HttpContext.User.Identity.Name.ToString(),
message + "(id=" + filterContext.RouteData.Values["id"] + ")");
}
}
but i ran into a wall trying to get the IoC to work in a custom attribute filter. scouring stackoverflow and google searches, i found that it's sort of difficult to do, with talk about using different wrappers, action invokers, etc, which all seemed more complicated than i was really willing to deal with.
trying to learn more about IoC (i'm still very new at this), i found this article,
which really helped point me in the right direction. i added his sealed AppServiceFactory class with my WindsorControllerFactory, and it worked like a charm.
As i said, i'm very new with to MVC and this IoC stuff, so i'm not sure this is an ideal way of handling things- but it seems simple and it works so far. I'd welcome any comments or criticisms on handling it through this method.
UPDATE
Figured out a different way of doing this- created a function in my WebUI project as such:
public static class Loggers
{
public static void WriteLog(ControllerContext controllerContext, LogLevel logLevel, string message)
{
ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
logWriter.WriteToLog(
controllerContext.RouteData.Values["controller"].ToString(),
controllerContext.RouteData.Values["action"].ToString(),
logLevel,
controllerContext.HttpContext.Timestamp,
controllerContext.HttpContext.User.Identity.Name.ToString(),
message);
}
}
now, wherever i want to log something, i can call
Loggers.WriteLog(
this.ControllerContext,
LogLevel.Membership,
"Removed role '" + role + "'" + " from user " + _userService.Get(id).UserName );
to write a record to the log. this gives me a lot more flexibility on my "message" content, and solves the problem of including logging in the global.asax file, which would've been difficult if not impossible using the attribute filters. i'll leave the rest, as it may be of use to someone else, but i think this is the way i'll go on this.
as usual, things are usually simpler in MVC than i original think they will be :)