Struts2- URL tag - Hide query String - url

After a lot of research on stackoverflow i'm posting this question as i could not find a solution for the issue.
Requirement Scenario : Update a customer from a list of customers based on each customer id as parameter.
Solution tried: Based on the customer Id received from the jsp, pass it to the Action as Struts2 url tag.
Issue Faced - Query String visible on the URL.
http://foo.com/Struts2Example/getCustomerAction?customerId=2
Questions :
Can we not hide the query string if we use struts Url tag?
If we cannot hide the using query string while using Url tag? what is the alternative for the above scenario.
Code for struts.xml,jsp and action below -
<h2>All Customers Details</h2>
<s:if test="customerList.size() > 0">
<table border="1px" cellpadding="8px">
<tr>
<th>Customer Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
<th>Created Date</th>
</tr>
<s:iterator value="customerList" status="userStatus">
<tr>
<td><s:url var="editCustomer" action="getCustomerAction">
<s:param name="customerId" value="%{customerId}" />
</s:url>
<p>
<s:a href="%{editCustomer}">
<s:property value="customerId" />
</s:a>
</p></td>
<td><s:property value="firstname" /></td>
<td><s:property value="lastname" /></td>
<td><s:property value="age" /></td>
<td><s:date name="createdDate" format="dd/MM/yyyy" /></td>
</tr>
</s:iterator>
</table>
</s:if>
<br />
<br />
struts.xml-
<!-- Get Customer Details - To Pre-Populate the form to update a Customer -->
<action name="getCustomerAction" method="getCustomerById"
class="com.hcl.customer.action.CustomerAction">
<result name="success">pages/customerForm.jsp </result>
</action>
Customer Action class-
public class CustomerAction extends ActionSupport implements ModelDriven {
Logger logger = Logger.getLogger(CustomerAction.class);
Customer customer = new Customer();
List<Customer> customerList = new ArrayList<Customer>();
CustomerDAO customerDAO = new CustomerDAOImpl();
public Customer getCustomer() {
return customer;
}
//Set Customer onto Value Stack
public void setCustomer(Customer customer) {
this.customer = customer;
}
public List<Customer> getCustomerList() {
return customerList;
}
//Set Customer List onto Value Stack
public void setCustomerList(List<Customer> customerList) {
this.customerList = customerList;
}
public String execute() throws Exception {
return SUCCESS;
}
public Object getModel() {
return customer;
}
// Edit customer details, it will retrieve the records based on customerId
//SkipValidation is used to skip the validate()
#SkipValidation
public String getCustomerById() {
logger.info("** Customer Id to edit ** " + customer.getCustomerId());
customer = customerDAO.customerById(customer.getCustomerId());
return SUCCESS;
}

Some unordered considerations:
use different Actions (with the execute method only), or different Methods of the same Action, to perform different "actions";
The name of each Action/Method should match the operation performed and be self-explanatory, for example you should have an editCustomer method (or Action) to edit the customer and a getCustomer method (or Action) to obtain the customer;
The GET HTTP method should be used to read data, while the POST HTTP method should be used to send data; every non-reading operation should ideally be performed through POST; using GET to send data is an old bad practice born 20 years ago and never died :/ The reasons to use POST are the hidden URL, a higher load capacity, the ability to send binary data, etc...
That said, an URL like http://foo.com/Struts2Example/getCustomerAction?customerId=2 should be visible (to be bookmarked for example), and ideally should be prettified (REST style, like StackOverflow): something like http://foo.com/Struts2Example/Customer/2/
An URL like http://foo.com/Struts2Example/editCustomerAction?customerId=2 can't work, because you are not passing any other parameter; you know the id of the customer to edit, but not the data to alter...
It would become something like:
http://foo.com/Struts2Example/editCustomerAction?customerId=2&name=foo&lastname=bar&age=42, that would work, but as said (and as ask in your question) should be hidden, and handled through POST.
If you are printing in the source of the page the IDs, then there should be no need to hide them to the user;
What you need to do is to ensure that the user can't change the IDs outside the range you specified;
if you drawed in the page a list of customers with ID {1,2,3} you must block any attempt of the user to alter the id and trying to update the customer with ID = 4... to achieve that, simply store the list of ID in session before populating the page, and check the IDs returned by the page against your list. If they don't match, block the malicious operation.
Hope that helps

An alternative , is to encrypt the userID and send it back to the HTML page. Maintain the Mapping on the client side. When you submit the request , POST the encrypted value. The decryption/encyrption logic will be on the server side.
This will add an overhead on the system but this is a decent enough trade-off to performance when compared to Security.
Also please take a look # jcryption.org/info , its under MIT and GPL Licenses.
A simpler solution is to convert this into "POST" action so that the values are passed inside the HTTP Request Body. If its over HTTPS , it would be encrypted however you can still do the user id lookup using Google Developer Tools or IE9 Developer mode

Related

How to obtain a directory extension in Azure AD using MS Graph

I'm trying to query a custom directory extension that was added to our user object in Azure AD. I am using the solution found here.
I'm able to get the property using the UserProfileController and updating the Model to have our custom extension property (see the two code snippets below).
Models/UserProfile.cs
public class UserProfile
{
public string DisplayName { get; set; }
public string GivenName { get; set; }
public string Surname { get; set; }
public string extension_ExtId_ExtName { get; set; }
}
View/UserProfile.cshtml
#model App.Models.UserProfile
<h2>#ViewBag.Title.</h2>
<table class="table table-bordered table-striped">
<tr>
<td>Display Name</td>
<td>#Model.DisplayName</td>
</tr>
<tr>
<td>First Name</td>
<td>#Model.GivenName</td>
</tr>
<tr>
<td>Last Name</td>
<td>#Model.Surname</td>
</tr>
<tr>
<td>Employee Id</td>
<td>#Model.extension_ExtId_ExtName</td>
</tr>
</table>
#if (ViewBag.ErrorMessage == "AuthorizationRequired")
{
<p>You have to sign-in to see your profile. Click #Html.ActionLink("here", "Index", "UserProfile", new { reauth = true }, null) to sign-in.</p>
}
#if (ViewBag.ErrorMessage == "UnexpectedError")
{
<p>An unexpected error occurred while retrieving your profile. Please try again. You may need to sign-in.</p>
}
My goal is to have the extension extension_ExtId_ExtName appear on a list of users. I am trying to use the solution's UsersController and view to obtain this information, but it appears that the Microsoft Graph API User model cannot be modified. The model is set to be of an IEnumerable<User> for which the Microsoft Graph Client controls.
How do I add my custom extension so that I can retrieve it from the User object as well?
I've confirmed that I can obtain it via the user object by going to the Graph Explorer and setting my request URL to:
https://graph.microsoft.com/beta/users('{user#email.com}')?select=extension_EXTENSION-ID_extensionName
Thanks
I think part of the problem here is that you're conflating two different API. There is the Microsoft Graph API and the Azure Active Directory Graph API; these are two entirely different APIs. While there is a lot of functional overlap between them, calls are not interchangeable between them.
I'd suggest taking a look at these Microsoft Graph API samples instead:
aspnet-snippets-sample
aspnet-connect-sample
aspnet-connect-rest-sample

jsf2.0 - How to get the values in other jsf page's bean in request scope

I have two pages myaccount.xhtml and selectbank.xhtml
In my account page there is one option for recharge account in which user will enter the amount when user will press submit button then it will goto the select bank page using following bean method.
public String gotoPayMethod() {
FacesMessage doneMessage=new FacesMessage("Redirecting to Payment Type Page");
FacesContext.getCurrentInstance().addMessage(null, doneMessage);
return "SelectBank";
}
When user will goto to selectbank there user will have to submit payment method but in this page it shows the amount as null which was entered in the previous page.
Both the pages are using the same bean and the scope of the bean is request scope.
So how can I access that value without passing this values through URL GET method.
Just for my satisfaction I used session scope then it was working but I know thats not the proper way because I start using session scope for each pages then it will not be efficient.
Thanks
Well, if your beans are RequestScoped than you don't have same bean for both pages. These beans are recreated for every request, so you should pass parameters. Change return statement of your gotoPayMethod() to:
return "SelectBank?faces-redirect=true&includeViewParams=true";
and on selectbank.xhtml add:
<f:metadata>
<f:viewParam name="amount" value="#{bean.amount}" />
</f:metadata>
Adapt this to your property and bean name.
If using parameters is not a solution you can add this parameter in the session, and remove it from session in second bean when you retrieve it:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("amount", amount);
((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().removeAttribute("amount");
Second construction for removing the attribute is necessary as Map returned from getSessionMap() is immutable.
You can use the #{flash} object that will keep your data until the next view. This way you won't need to deal with view parameters.
Details from myaccount.xhtml:
<h:form>
<h:outputText value="Enter amount: " />
<h:inputText value="#{flash.amount}" />
<br/>
<h:commandButton value="Go to payment method" action="#{bean.gotoPayMethod}" />
<h:form>
Bean of both views:
#ManagedBean
#RequestScoped
public class Bean {
#ManagedProperty("#{flash}")
private Flash flash;
private int amount = -1;
public Bean () { }
public String getAmount() {
if(amount == -1) {
int val = Integer.parseInt((String)flash.get("amount"));
flash.keep("amount");
amount = val;
}
return amount;
}
public Flash getFlash() {
return flash;
}
public void setFlash(Flash flash) {
this.flash = flash;
}
public String gotoPayMethod() {
//do business job
return "SelectBank?faces-redirect=true";
}
}
Details from selectbank.xhtml:
<h:outputText value="Amount entered by user is #{bean.amount}" />
Your use case is not of simple request/response cycle, the life span is more than one request response which makes it candidate for session scope.
Using hidden variable or GET parameters in URL is not good practice especially for a banking application. Where security is so important dont compromise on small memory foot print.
If flash scope map simplifies the case you can use it, but I would not go for such a thing.
Update: Forgot to mention you can check Conversation scope too.

How to update session values from JSP in Struts 2

I am using Struts 2.0. I have a Java Bean Person having fields perName, perAge, perMail & many more. I want to display a Map of Java Bean {[1, person1], [2, person2]) on JSP and allow the user to update it from the same JSP using text fields. There are lot of variables in the bean and some of them are editable while some of them are not.
For example, perName is not editable while perAge is editable. I don't want to display non editable fields. If I use ediatable fileds only, after updating, I get non editable fields as null (perName is null after update). So I can't specify name attribute as it is changing at run time. So I am putting them in HTTP Session and displaying them. I am specifying name attribute of text field using #session.person[iterator index].perAge. Till this point everything works fine. But if I change the value in any text field & try to update, I get the old session attribute instead of changed one. I want the old session attribute with the new changed values and values of non editable fields should persist within user request. I don't want to use JavaScript. OGNL or expressions are most welcome.
public class PersonDTO implements Serializable {
private String perName;
private int perAge;
public String getPerName() {
return perName;
}
public void setPerName(String perName) {
this.perName = perName;
}
public int getPerAge() {
return perAge;
}
public void setPerAge(int perAge) {
this.perAge = perAge;
}
}
<s:form action="updatePerson" id="updatePerson">
<table>
<tr>
<td>AGE:<s:textfield name="#session.person.perAge" />
</td>
</tr>
<tr>
<td><s:submit id="update" value="Update" />
</td>
</tr>
</table>
</s:form>
Thanks for your support. After a day long GOOGLE, I found that it is not possible to update session directly using Struts tags. You can use session information for display and update session in scriplets but you can't update session directly. You may refer Struts2 form to update object in Session map? for more info. Once again thanks for help!!!

What are the security reasons for not allowing get requests with MVC/ajax? [duplicate]

As part of the ASP.NET MVC 2 Beta 2 update, JSON GET requests are disallowed by default. It appears that you need to set the JsonRequestBehavior field to JsonRequestBehavior.AllowGet before returning a JsonResult object from your controller.
public JsonResult IsEmailValid(...)
{
JsonResult result = new JsonResult();
result.Data = ..... ;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
What is the reasoning behind this? If I am using JSON GET to try and do some remote validation, should I be using a different technique instead?
The reason for the DenyGet default is on MSDN with a link to Phil Haack's blog for further details. Looks like a Cross-Site scripting vulnerability.
HTTP GET is disabled by default as part of ASP.NET's Cross-Site Request Forgery (CSRF/XSRF) protections. If your web services accept GET requests, then they can be vulnerable to 3rd party sites making requests via <script /> tags and potentially harvesting the response by modifying JavaScript setters.
It is worth noting however that disabling GET requests is not enough to prevent CSRF attacks, nor is it the only way to protect your service against the type of attack outlined above. See Robust Defenses for Cross-Site Request Forgery for a good analysis of the different attack vectors and how to protect against them.
I also had your problem when I migrated my MVC website from Visual Studio 2008 to Visual Studio 2010.
The main aspx is below, it has an ViewData which calls a Category Controller in order to fill up ViewData["Categories"] with SelectList collection. There's also a script to call a Subcategory Controller to fill up the second combo with javascript. Now I was able to fix it adding up AlloGet attribute on this second controller.
Here's the aspx and javascript
<head>
<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryId").change(function () {
var categoryId = $(this)[0].value;
$("#ctl00_MainContent_SubcategoryId").empty();
$("#ctl00_MainContent_SubcategoryId").append("<option value=''>-- select a category --</option>");
var url = "/Subcategory/Subcategories/" + categoryId;
$.getJSON(url, { "selectedItem": "" }, function (data) {
$.each(data, function (index, optionData) {
$("#ctl00_MainContent_SubcategoryId").append("<option value='" + optionData.SubcategoryId + "'>" + optionData.SubcategoryName + "</option>");
});
//feed our hidden html field
var selected = $("#chosenSubcategory") ? $("#chosenSubcategory").val() : '';
$("#ctl00_MainContent_SubcategoryId").val(selected);
});
}).change();
});
</script>
<body>
<% using (Html.BeginForm()) {%>
<label for="CategoryId">Category:</label></td>
<%= Html.DropDownList("CategoryId", (SelectList)ViewData["Categories"], "--categories--") %>
<%= Html.ValidationMessage("category","*") %>
<br/>
<label class="formlabel" for="SubcategoryId">Subcategory:</label><div id="subcategoryDiv"></div>
<%=Html.Hidden("chosenSubcategory", TempData["subcategory"])%>
<select id="SubcategoryId" runat="server">
</select><%= Html.ValidationMessage("subcategory", "*")%>
<input type="submit" value="Save" />
<%}%>
here's my controller for subcategories
public class SubcategoryController : Controller
{
private MyEntities db = new MyEntities();
public int SubcategoryId { get; set; }
public int SubcategoryName { get; set; }
public JsonResult Subcategories(int? categoryId)
{
try
{
if (!categoryId.HasValue)
categoryId = Convert.ToInt32(RouteData.Values["id"]);
var subcategories = (from c in db.Subcategories.Include("Categories")
where c.Categories.CategoryId == categoryId && c.Active && !c.Deleted
&& c.Categories.Active && !c.Categories.Deleted
orderby c.SubcategoryName
select new { SubcategoryId = c.SubcategoryId, SubcategoryName = c.SubcategoryName }
);
//just added the allow get attribute
return this.Json(subcategories, JsonRequestBehavior.AllowGet);
}
catch { return this.Json(null); }
}
I don't know if this is the reason they chose to change that default, but here's my experience:
When some browsers see a GET, they think they can cache the result. Since AJAX is usually used for small requests to get the most up-to-date information from the server, caching these results usually ends up causing unexpected behavior. If you know that a given input will return the same result every time (e.g. "password" cannot be used as a password, no matter when you ask me), then a GET is just fine, and browser caching can actually improve performance in case someone tries validating the same input multiple times. If, on the other hand, you expect a different answer depending on the current state of the server-side data ("myfavoriteusername" may have been available 2 minutes ago, but it's been taken since then), you should use POST to avoid having the browser thinking that the first response is still the correct one.

How to pass progress to MVC page

I have a delegate method with is called periodic while WritingAnObject uploading the file. I would like to update div (ProgressUpdate) in my MVC page with args.PercentDone value. I appreciate any idea?
Thanks,
//delegate method
private void displayProgress(object sender, ProgressArgs args)
{
//Console.WriteLine(args.PercentDone); //I want to display args.PercentDone in the page
}
//Controller
[HttpPost]
public ActionResult WritingAnObject(MyViewModel bovModel)
{
//DoSomeStuff which is cause calling displayProgress
return RedirectToAction("ListingSomeInfo", "testpart");
}
//View
<%using (Html.BeginForm("WritingAnObject", "testpart", FormMethod.Post, new { enctype = "multipart/form-data" }))
{%>
<%:Html.TextBox("catname") %>
<input type="file" id="fileupload" name="fileupload" />
<input type="submit" value="Upload" />
<%} %>
<div id= “ProgressUpdate”</div>
Here is one approach you could take to display progress back to a user while an operaton on the server is completing. (requires javascript)
1) Write an action that starts the process on the server. This method should update a progress value in session state (so that it is specific to each session the user is running).
2) Write an action that the client can call to return progress. This would read the value in session state. Generally this action will return either a small HTML fragment containing the progress bar filled in to the right amount, or a JSON object containing the progress value.
3) From your client, make a jQuery.ajax() call to asynchronously poll the server for progress while the operation is running and update the UI.
Additional bells&whistles:
- an Action to cancel a long running operation
- running the task outside the web application (Azure has some excellent features regarding running tasks asynchronously from a web app)
- Have the action that returns progress also let the client know if the operation is completed or canceled.

Resources