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.
Related
I have an angularjs application, in this application I have a login form when I submit it I call a rest service to authenticate the user to my server application, as following :
$http.get('http://localhost:8080/user', {
headers : credentials ? {
authorization : "Basic "
+ btoa(credentials.username + ":"
+ credentials.password)
} : {};
}).then(function(response) {
if (response.data.name) {
$rootScope.authenticated = true;
$rootScope.username=response.data.name;
$rootScope.roles=response.data.authorities;
$rootScope.sessionid=response.data.details.sessionId;
} else {
$rootScope.authenticated = false;
}
}, function() {
$rootScope.authenticated = false;
});
So the $rootScope will have all the informations about the authenticated user, but when I refresh my application, all those informations I attached to $rootScope are removed.
Notice that http://localhost:8080/user will always maintain the session.
How can I solve that ?
You can either store it in sessionStorage or just get the current user logged from server side. Then in order to retrieve them use an angular.run
angular.run(...function($http, $rootScope){
// either use session storage or $http to retrieve your data and store them in $rootScope.
// if you use $http i suggest you to store the promise of $http to be sure in your controller/route to wait that it has been resolved.
});
The fact that you're loosing what you store when using f5 is normal, you lose all javascript context when doing so. The usage of angular.run permit to use the request before any controller is called However with $http you may need to wait the end of the promise. So it's better to have a reference to the promise store in $rootScope to be able to use it in the javascript part. You can reference directly the data in the templates as they will get refresh as soon they will be loaded.
Check for Local and Session storage service. You can easily attach informations to variables with getters and setters, and retrieving them through page refreshing.
Example: You can set a variable like this:
localStorageService.set('myVar', data);
And then retrieve it in another controller, after refreshing, or elsewhere in your application with:
localStorageService.get('myVar');
It is rather well documented and easy to use.
I have used CakePHP + AngularJS for the application
I have below code in Sevices file
test.factory('Dashboard', function ($http, $q) {
return {
userDirectory: function (){
return $http.get(hostName + 'dashboards/userDirectory.json');
}
}
});
The above code calls dashboards's controllers userDirectory function and return JSON data this is how it's work.
Some one raised one issue, When he hit url "http://hostname/dashboards/userDirectory.json" he can see the response data in browser and that is not authenticated. Is there any way through which I can secure it.
By any encoding/decoding or What you prefer.
Decode/encode doesn't make any sense here if the client can decode it the user can get the data as well.
Just send data the user is allowed to see and use, even if he is authorized for that request, remove everything else that is not needed.
Use a JWT token to authorize them
https://github.com/ADmad/cakephp-jwt-auth
http://www.bravo-kernel.com/2015/04/how-to-add-jwt-authentication-to-a-cakephp-3-rest-api/
http://florian-kraemer.net/2014/07/cakephp-and-token-based-auth-with-angular-js/
I'm trying to make a global variable called theUser which contains the userinfo if logged in.
I have tried putting this in my SPA php file:
app.value('theUser', '<?php echo Auth::user(); ?>');
And it works but only after refreshing page. (Login happens via angularjs logic + a $http request to auth/login which returns userinfo if logged in)
In my angular auth app, I have done this:
var login = $http.post("auth/login", sanitizeCredentials(credentials)).success(function(data) {
theUser = data;
$rootScope.theUser = theUser;
});
And that works, but only when the user logs in. If I refresh, theUser is empty. And I can't get these two solutions to work together. I probably need another approach.
All I want is an user variable that I can access from anywhere in my app,
which is set if the user logs in, or have been logged in before. Using Laravel 5.1.
Here is my auth app service js: http://pastebin.com/HcdLaZcD
How can I make this work?
Why dont you use PHP-Vars-To-Js-Transformer by Laracasts. Then whenever a User logs in, you could set a Session variable auth_user and then get that variable to JavaScript as shown below (in your Laravel AuthController#login):
...
\Session::put('auth_user', \Auth::user());
JavaScript::put([
'theUser' => \Session::get('auth_user')
]);
...
And when the User logs out: \Session::forget('auth_user');
theUser variable will be available anywhere in your JavaScript (or you can Namespace it also, check the Github link above).
on top of the page under script tag
window.user = <?php echo Auth::user(); ?>
and
app.value('theUser',window.user);
app.run(function ($rootScope, theUser) {
$rootScope.theUser = theUser;
});
For accessing the logged in user from your JavaScript files, you may try something like this (Create a view composer, also layouts.master dictates layouts/master.blade.php):
View::composer('layouts.master', function($view) {
$user = null;
if(Auth::check()) {
$user = Auth::user();
}
$view->with('authUser', $user);
});
In the master layout try this (So User variable will be available as JS object if the user is logged in):
<head>
<script>var User = {{ $authUser or 'undefined' }}</script>
</head>
This is just an idea, implement it according to your need. Also, you may use a namespace like App.user. I wrote an article about this lasr year, you may
check it here. Btw, it was for Laravel 4.x.
.
We have made use of html5 local storage to overcome this once the user is logged in, you just put the user's info on html5's local storage (works on all browsers, even mobile).
It has some drawbacks which you have to overcome, and also have some control on your routes filters to avoid someone loading page they shouldn't be allowed to see.
But I'm afraid my answer applies better to our solution and I don't think this answer is perfect but might guide you in a better solution. Our app publishes an API for angular's use and this angular is somewhat empowered with some extensions to ease routing.
I have implemented the authentication/authorization using AngularJS, Jersey REST and Spring Security. After logged in, call the following "create" method to store the user information:
.factory('Session', function () {
this.create = function (user) {
this.id = user.sessionId;
this.username = user.username;
this.userRoles = user.roles;
};
... ...
return this;
})
But, the problem is, every time I do one of the following 2 things, the stored information is lost and I have to login again:
Reload the whole page by pressing F5 or reload icon of browser
OR
Access the same URL from browser address bar
Could you please help me on how to reserve this information to guarantee login only once?
Thanks,
Check out sessionStorage. Not sure what the rest of your code looks like, but presumably your controller could save the Session created by your factory into sessionStorage.
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.