We are experiencing an edge-case error with ASP.NET Web Api 2 and MSSQL. The situation is this:
An external process is storing a complex token in a database record
along with a simpler token that identifies the record.
The external process then redirects the user to an endpoint in our API passing the simple token in the url.
The API uses the simple token to look up the database and retrieve the complex token
The user is then redirected to another url with the complex token injected into the window object of the response.
Here is the problem:
Two simultaneous requests, from different users, come in to retrieve complex tokens the server. The first request fails. The second request gets served the complex token that is associated with the first request.
This only occurs when the Windows Server is waking from sleep.
At all other times the users send in their simple token and receive back the correct complex token.
Can anybody shed any light on what is causing the problem and how to fix?
A simplified version of the code that is associated with this case is here:
// The Controller action that receives the simple Token
public ActionResult GetToken(string simpleToken)
{
ApiOutput.UserToken.Token = QueryToken(simpleToken);
return RedirectToAction("Index");
}
// The method that retrieves the complex token from the database
public static string QueryToken(string simpleToken)
{
using (var _wdb = new AppDbContext())
{
var data = _wdb.TokenData.FirstOrDefault(d => d.SimpleToken == simpleToken);
return data.ComplexToken;
}
}
// Controller Index action
public ActionResult Index()
{
return View();
}
<!-- The Index view where the complex token is returned -->
#{ Layout = null; }
#using myApp.Models
#model ApiOutput.UserToken
<!DOCTYPE html>
<html>
<body>
<script>
window.dbtoken = "#ApiOutput.UserToken.Token";
</script>
</body>
</html>
Related
I want to ultimately have user sessions end once the browser or tab is closed, and so far i had no luck. I have tried to enable offline_access in the IdentityServer config and in the client config but that doesn't seem to help. I am seeking some help with having my setup function in this way.
I use the flow of SignIn that redirects you too the IS4 login page then upon successful login you get redirected to the client app.
Here's how I handle it: I'm using a JavaScript sessionStorage variable to sense when the user has closed the browser (or tab).
<script>
var readValue = sessionStorage['checksession'];
</script>
If the browser was closed the variable will be undefined. In that case, I call a server-side page method to redirect the user to the login form:
<script>
var readValue = sessionStorage['checksession'];
if (readValue == null) {
// Redirect to Login
PageMethods.BrowserClosed();
}
</script>
Server side page method must be static and marked as [WebMethod]:
[WebMethod]
public static void BrowserClosed()
{
Util.hasClosedBrowser = true;
}
The static web method updates a boolean property in a static utility class (Util.cs) that I use in my asp.net project.
In Util.cs:
public static bool hasClosedBrowser { get; set; }
In the asp.net Page.Load event, I am looking for a "true" value in the "hasClosed" property defined in the utility class. If it's true, I call the Logout() method, which redirects to the login form:
if (Util.hasClosedBrowser)
{
Logout();
return;
}
At the end of the .aspx page after all of the elements, in a script tag I am setting the sessionStorage variable:
sessionStorage['checksession'] = "somevalue";
You can use any value in the sessionStorage cookie that you want, just know that it has to be a string unless you want to format it as a JSON string.
What's great about this approach is it correctly redirects to the Login form when the browser or the tab page was closed, but does not fire when the user simply refreshes the page (assuming the session hasn't actually expired). On a refresh, and as long as the session has not expired, the user's login state remains intact because the variable will still be present in sessionStorage.
Cheers,
-=Cameron
I have set up my spring to maintain a HTTP session on an object like so:
#Component
#SessionScope
public class Basket { .. }
controller:
#PostMapping(path="/basket/addItem/{user}", consumes = "application/json", produces = "application/json")
public Basket createBasket(#PathVariable String user, #RequestBody Item item) {
System.out.println("POSTING..................................");
return basketService.addItem(user, item);
}
now when i use a REST client, in firefox i can see that the session bean is created and maintained for the duration - multiple calls. I can append to the object. If i try another client, it gets its own session with its own bean. great..
spring logs the following:
Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [269] milliseconds.
However im trying to create a basic front end in react, when react makes a request using axios it gets a new bean every time, which means that the session must be ending after each call. IS that correct? or im not tying it to the react application...
Maybe the approach im taking is not correct, maybe i should use a a different approach, Im trying to learn about spring boot, so its a basic project... and right now i want to maintain user session for a cart. so subsequent calls i can append to the object...
by adding the following to my controller it all began to work.
#CrossOrigin(origins = { "http://localhost:3000" }, allowedHeaders = "*", allowCredentials = "true")
I am creating a project in AngularJs at frontend and Spring MVC in backend.
Now assume when a used logged in and if he wants to update his information, for this i have created an api which request for emailid and update the rest object in database of that email id
Now i have some questions,
1.) I dont want to use CookieStore or others sessionStorage or localstorage (because of my personal vulnerability experience and also i want to use session only) in Angular, how can i do it in angular with Spring MVC.
2.) How can i retrieve the email id from session to update data?
3.)If a user goes to another page how can i maintain that session in another page, how can i check that session is there and user is authentic to see the page
Read a lot about it but unable to find the exact solution with session. Answer over there is manage it by cookieStore.or localstorage, Please help
Let's try and see what is happening here using cookies is the right way to this, you may think it is not safe but is the safest way to do it. With cookies you will be sharing the same session in all tabs, so you can handle in all tabs and share it.
There is also an alternative option and is using URL rewriting, quoting #vanje in this question in stackoverflow
the session is only identified via a URL parameter containing the session ID. So every internal URL of your web application has to be enhanced with this parameter using the method HttpServletResponse.encodeURL(). If you are using a web framework like Wicket, chances are good that this is already done for you.
Lets go now with the Angular JS - Spring MVC approach:
There is no need to access the session within the Angular JS front-end, if you need to use it and you are using JSP you may use scriplet to retrieve the information openening a <%= session.getAttribute("user") %> , but as I said there is no need to do this. You may call your function, and retrieve this information in your controller in Spring.
You have a controller in angular JS that calls with http to your REST controller in Spring such like this. assuming that you save your user first in session:
$scope.getUserInfo= function () {
$http.get(appContextPath +'/rest/getuser/').success(function (data) {
$scope.user= data;
});
};
You may have a request mapping for the URL above:
#RequestMapping(value = "/rest/getuser", method = RequestMethod.GET)
#ResponseBody
public User getUserInfo (HttpSession session) {
User nUser = session.getAttribute("user");
return nUser;
}
I think the best way is to create a method in your AngularJS controller and then call it.
Java code:
#RequestMapping(value = "/menu/get", method = RequestMethod.GET, headers="Accept=*/*")
public #ResponseBody Empleado showMenu(HttpSession session) {
Empleado empleado = (Empleado) session.getAttribute("empleado");
return empleado;
}
AngularJS code:
angular.module('myModule')
.controller('myMenuController', ['$scope', '$http'
function($scope, $http){
getEmpleadoInfo = function () {
$http.get(myContextPage + '/menu/get')
.then(function(data) {
$scope.empleado = data;
})
}
getEmpleadoInfo();
}]);
This way, when you load the page, the object will be loaded on the scope.
I'm new to AngularJS and I'm starting to create a sample application, this application has 2 views:
Login View
Welcome View
Everything is working fine with my AngularJS dummy application but now I start implementing the Login functionality on server side:
[HttpPost]
public JsonResult Login(string credentials)
{
bool returnVal = false;
if (!string.IsNullOrEmpty(credentials))
{
FormsAuthentication.SetAuthCookie("DUMMY USER", true);
}
return Json(new
{
success = returnVal
},
JsonRequestBehavior.AllowGet);
}
And on Welcome Controller I have:
[Authorize]
public JsonResult GetPersons()
{
return Json(new
{
success = false
},
JsonRequestBehavior.AllowGet);
}
Then in order to implement the Forms Authentication I have to set in the Web.Config:
<authentication mode="Forms">
<forms loginUrl="/login" name=".ASPXFORMSAUTH" protection="All" timeout="1" slidingExpiration="true" />-->
</authentication>
The problem is that when doing that it will redirects the URL, so I get the following error:
GET http://localhost:21871/login?ReturnUrl=%2fperson%2fGetPersons 404 (Not Found)
And because AngularJS can't understand that route then I can't keep going.
Any clue on how to address this or maybe there is a better way to do it.
Thanks
You can use any authentication/authorization mechanism that you like. But when you are calling $http.get() or $http.post() you expect to receive a JSON object. But if you are not authenticated you will be redirected to login page which is an HTML page. Hence your code which is checking for success will fail.
You need to create a new custom authorize filter (like MyAuthorize) that authenticate/authorizes your user by any available technology (SimpleMembership, OAuth, etc) and if authentication fails then instead of returning a RedirectResult, returns a JSON object with an Error flag. Then you can check that flag after each $http.get() or $http.post(), and redirect the user from client side. We always develop our own communication service that calls $http.get() or $http.post and always make that check over there.
I am a new bie on GWT, I wrote an application on abc.com, I have another application i.e. xyz.com, xyz.com?id=1 provides me a data in json format, I was thinking to find a way that how to get that json file in abc.com via RPC call, because I have seen tutorials in which RPC calls are used to get data from its server. any help will be appreciated.
EDIT
I am trying to implement this in this StockWatcher tutorial
I changed my code slightly change to this
private static final String JSON_URL = "http://localhost/stockPrices.php?q=";
AND
private void refreshWatchList() {
if (stocks.size() == 0) {
return;
}
String url = JSON_URL;
// Append watch list stock symbols to query URL.
Iterator iter = stocks.iterator();
while (iter.hasNext()) {
url += iter.next();
if (iter.hasNext()) {
url += "+";
}
}
url = URL.encode(url);
MyJSONUtility.makeJSONRequest(url, new JSONHandler() {
#Override
public void handleJSON(JavaScriptObject obj) {
if (obj == null) {
displayError("Couldn't retrieve JSON");
return;
}
updateTable(asArrayOfStockData(obj));
}
});
}
before when I was requesting my url via RequestBuilder it was giving me an exception Couldn't retrieve JSON but now JSON is fetched and status code is 200 as I saw that in firebug but it is not updating on table. Kindly help me regarding this.
First, you need to understand the Same Origin Policy which explains how browsers implement a security model where JavaScript code running on a web page may not interact with any resource not originating from the same web site.
While GWT's HTTP client and RPC call can only fetch data from the same site where your application was loaded, you can get data from another server if it returns json in the right format. You must be interacting with a JSON service that can invoke user defined callback functions with the JSON data as argument.
Second, see How to Fetch JSON DATA