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/
Related
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.
So, I have been working on this exercise and I'm down to one final problem.
The JSON is on a different server. If I use a plain old $http.get then it doesn't allow the cross-server request. When I switch and use $http.jsonp I get to the file but it claims an unexpected ":" right away. I've validated their JSON so I'm not sure what's going on.
This is the current implementation of the call:
app.factory('users', ['$http', function($http) {
return {
callExternalJson: function() {
return $http.jsonp('http://applicant.pointsource.us/api/testUser/577ebf34f62a2d8f3c05d9c0?callback=JSON_CALLBACK').then( function(response) {
return response;
});
}
}
}]);
How do I get that remote JSON file?
Something to note: that remote JSON changes every time you hit it.
I also tried a different way of using jsonp that I've used in the past to access other RESTful APIs and got the same result of it choking on their first colon.
The problem isn't your code, but instead the server.
Try replacing the URL with this Test URL that supports JSONP. http://ip.jsontest.com/?callback=JSON_CALLBACK
I am storing authentication token in $rootScope . This token will be sent as part of header in every request via interceptor.
<code>
$rootScope.jwtToken=successfulResponse.data.body;
</code>
Interceptor code is as below :-
var bpInterceptor = function($q,$rootScope){
return {
request : function(config){
if($rootScope.jwtToken !== undefined){
config.headers.Authorization = $rootScope.jwtToken.token;
}
return config;
}
}
};
</code>
Q) Does $rootScope have different object for two browser sessions?
Angular code is executed client side only, so any state will disappear once you reload the page.
If you want to keep information between two user session, you have many options:
Keep that info in the URL using $location or location
Store that info in localStorage and retrieve it next time
Persist the information server side and query your server to get it back
Follow-up:
Once you get your token you can do:
localStorage.setItem('myToken', $rootScope.jwtToken);
And when you load your application, check if a token has been stored:
$rootScope.jwtToken = localStorage.getItem('myToken');
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 the following OrientDB function:
http://localhost:2480/function/Application/getPassFailCount/9:600
And it returns the following JSON result:
{"result":[{"#type":"d","#version":0,"pass":16.0,"fail":2.0,"#fieldTypes":"pass=d,fail=d"}]}
What I need to do is to get the values of "pass" and "fail" to use in my web page.
So far I have done this with AngularJS:
$http.get('http://localhost:2480/function/Application/getPassFailCount/9:600').
success(function(data) {
$scope.data = data.result;
// $scope.passCount = ;
// $scope.failCount = ;
});
Currently it gives the error "401 Unauthorized". How do I authenticate the request?
And if possible, can anyone give some tips on how to get the passCount and failCount from the JSON result returned?
The OrientDB HTTP API documentation states that you have to use HTTP Basic authentication for issuing commands. That means you have to include an Authorization header along with your request.
There are a few ways to achieve this, here is a simpler one. Use the configuration object parameter for $http.get to set the header on the request:
function base64(str) {
return btoa(unescape(encodeURIComponent(str)));
}
$http.get('http://...', {
headers: { 'Authorization': 'Basic ' + base64(user + ':' + password) }
}).success(...);
You should definitely move all your database logic to an Angular service, so you can keep this code in one place instead of polluting your controllers.
To make it even cleaner, you could look into $http interceptors and write a request interceptor that adds the header to every HTTP call.
Regarding the JSON question: you can see that the result object contains an array with a single element. Use indexing to get the actual record.
var result = data.result[0];
$scope.passCount = result.pass;
$scope.failCount = result.fail;
If you wrote a service as I mentioned, you could hide this implementation detail from your controller.
function getCount() {
return $http.get(...).then(function (data) {
var result = data.result[0];
// the caller will only see this simpler object
return { pass: result.pass, fail: result.fail };
});
}