When I try to access WebApi from MVC, I get this error
XMLHttpRequest cannot load http://localhost:57997/Home/Get. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:64035' is therefore not allowed acces
Service.Js
app.service('MyService', function ($http) {
var ApiAddress = "http://localhost:57997/";
this.GetWebData = function () {
var Getdatas= $http({
url: ApiAddress + 'Home/Get',
type: 'GET',
dataType: 'json',
params: JSON.stringify(),
content:{'content-type' :'application/Json'}
})
return Getdatas;
}
});
Controller.Js
app.controller('WebCtrls', function ($scope,MyService) {
$scope.Hello = "Hello angular How r u...";
$scope.GetDb = function () {
alert('Hello..');
var SerData = MyService.GetWebData();
SerData.then(function (d) {
$scope.Emp = d.data;
})
}
})
WebApi
public JsonResult Get()
{
var x = prod.GetEmployees();
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Global.asax
in WebApi global file I wrote bellow code for cross page origin
protected void Application_BeginRequest()
{
string[] allowedOrigin = new string[] { "http://localhost:57997/" };
var origin = HttpContext.Current.Request.Headers["Origin"];
if (origin != null && allowedOrigin.Contains(origin))
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET,POST");
//Need to add more later , will see when required
}
}
You can handle it by disabling web security option of chrome browser by following command from the folder location where chrome.exe is present. First close all instances of chrome. Then run following command
chrome.exe --disable-web-security
You can handle it at server side while filtering all request coming to server, add the header to response like this.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
Related
I have Angularjs app connects to a server using API, and i'm using token authentication, when i use Postman to get the token, it works perfect, but when i'm use Angulajs with the same header and parameters i got error:400.
When i checked both requests using Fiddler, i found that the request from Angularjs is missing Access-Control-Allow-Origin: * header.
How to fix this?
Here is the service used to get the token:
AuthenticationApi.Login = function (loginData) {
//POST's Object
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
//the data will be sent the data as string not JSON object.
$http.post('http://localhost:53194/Token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.then(function (response) {
console.log(response);
localStorageService.set('authorizationData',
{
token: response.access_token,
userName: loginData.userName
});
Authentication.isAuth = true;
Authentication.userName = loginData.userName;
console.log(Authentication);
deferred.resolve(response);
},
function (err, status) {
logout();
deferred.reject(err);
});
return deferred.promise;
};
for the API server, i'v done CORS:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
i found the problem and i fixed it.
in the API server, i have this code:
var cors = new EnableCorsAttribute("*", "*", "*");
cors.PreflightMaxAge = 60;
config.EnableCors(cors);
The problem is in the PreflightMaxAge, i just commented it...It worked!!!
if the problem not solved, try to use IE or FireFox, don't use Chrome because it is not CORS enabled
We are developing a web application, we're using Spring MVC (along with Spring Boot and Spring Security) and AngularJS.
Therefore, we have two distinct servers running for the application.
We are trying to store the user session backend, to ensure a proper level of security, so we tried to use the HttpSessionobject, but every time we want to retrieve the existing session, a new instance is created (we've checked the session ids).
Here's what we're doing to login :
$scope.authenticate = function () {
var postObject = new Object();
postObject.mail = $scope.userName;
postObject.password = $scope.userPassword;
$http({
url: "http://localhost:8080/login",
method: "POST",
dataType: "json",
data: postObject,
headers: {
"Content-Type": "application/json"
}
}).success(function successCallback(response, status) {
if (status == 200) {
$scope.messageAuth = "Login successful"
$scope.go('/services');
}
})
.error(function errorCallback(error, status) {
$scope.messageAuth = "Error " + response;
});
};
Then, we check the credentials, if they are correct, we store the user information into a new session :
#RestController
public class UserController {
#Resource
UserService userService;
#CrossOrigin
#RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<User> loginSubmit(#RequestBody User user, HttpServletRequest request, HttpSession session) {
if (isAuthorized(user)) {
User authenticatedUser = this.userService.getUserByMail(user.getMail());
authenticatedUser.setPassword(null);
session.invalidate();
HttpSession newSession = request.getSession(true);
newSession.setAttribute("USER_ROLE", authenticatedUser.getRole());
System.out.println("/login : SESSION ID = " + newSession.getId());
System.out.println("/login : " + newSession.getAttribute("USER_ROLE"));
return ResponseEntity.ok(authenticatedUser);
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(null);
}
}
#RequestMapping("/user")
public String user(Principal user, HttpServletRequest request, HttpSession session) {
System.out.println("/user : SESSION ID = " + session.getId());
System.out.println("/user : " + (String) request.getSession(false).getAttribute("USER_ROLE"));
return (String) session.getAttribute("USER_ROLE");
}
And finally, from the Angular app, we'd like to get the user information by calling /user like this :
var f = function() {
$http.get('http://localhost:8080/user').success(function successCallback(response) {
console.log(response);
}).error(function() {
console.log('error');
})
};
We've already tried pretty much every we found about how to manage a session with Spring Security, maybe the problem comes from the Angular part?
Any help would be greatly appreciated,
Thanks in advance
We found the solution, we just needed to add a few config lines in our app.js file :
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
More information here : link
Hopefully it will help someone, someday!
I am using parse.com cloud code and has a function inside, which is called using a https post call from my angularjs.
When I test the same function from POSTMAN REST client it works.
But from my domain it gives a CORS error
XMLHttpRequest cannot load
https://api.parse.com/1/functions/sendemail. Response to preflight
request doesn't pass access control check: A wildcard '*' cannot be
used in the 'Access-Control-Allow-Origin' header when the credentials
flag is true. Origin 'http://www.crickify.com' is therefore not
allowed access.
Cloud Code:
Parse.Cloud.define("sendemail", function(request, response) {
//response.success("Hello world!");
var mailgun = require('mailgun');
console.log("from parselog",request.params);
response.set("Access-Control-Allow-Origin", "http://www.crickify.com");
response.set("Access-Control-Allow-Headers", "X-Requested-With");
response.set('Access-Control-Allow-Headers', 'Content-Type');
mailgun.initialize('XXX', 'XXX');
mailgun.sendEmail({
to: "bala#mindlens.com.sg",
from: "Mailgun#CloudCode.com",
subject: "Hello from Cloud Code!",
text: "Using Parse and Mailgun is great!"
}, {
success: function(httpResponse) {
console.log(httpResponse);
response.success("Email sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error(httpResponse);
}
});
});
Angular Code:
$scope.sendemail = function(passedEmail) {
// body...
var email = passedEmail;
var message = {mail:email};
$http({
method: 'POST',
url: 'https://[app key]:jskey]#api.parse.com/1/functions/sendemail',
data: message
})
.success(function(data) {
console.log("Success" + data);
})
.error(function(error) {
console.log("Success" + data);
});
}
I wrote this in AngularJS service block and I can't get it to work properly:
app.factory('sfAttachment', ['$http', '$q', '$window', function($http, $q, $window){
var attachment = {};
//Save to server function for attachments
attachment.save = function( base64value, mimeType, currentDocTypeId, currentFilename, attachmentId ){
var data = {
"Body" : base64value,
"ContentType": mimeType,
"ParentId": currentDocTypeId,
"Name": currentFilename
};
var url = $window.__url;
var method;
var isUpdate = ($.trim(attachmentId) !== '');
if (isUpdate) {
url = url + attachmentId;
method = 'PATCH';
} else {
// Method for creation
method = 'POST';
};
var request = {
url: url,
method: method,
data: data
};
var deferred = $q.defer();
$http(request).then(function(response){
deferred.resolve(response);
console.log('file SAVED');
console.log(response);
}, function(event){
deferred.reject('The attachment could not be saved:' + event);
});
return deferred.promise;
}
return attachment;}]);
app.run(['$http','$window',function ($http, $window) {
var sessionId = $window.__sfdcSessionId;
$http.defaults.useXDomain = true;
delete $http.defaults.headers.common["X-Requested-With"];
$http.defaults.headers.common["Access-Control-Allow-Origin"] = "*";
$http.defaults.headers.common["Accept"] = "application/json";
$http.defaults.headers.common["content-type"] = "application/json";
$http.defaults.headers.common['Authorization'] = "OAuth " + sessionId ;
$http.defaults.headers.common['X-User-Agent'] = "MyClient" ;
}]) ;
I keep getting these errors:
Failed to load resource: the server responded with a status of 400 (Bad Request)
As well as this:
MLHttpRequest cannot load https://youri.cs22.my.salesforce.com/services/data/v26.0/sobjects/Attachment/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://youri--c.cs22.visual.force.com' is therefore not allowed access. The response had HTTP status code 400.
I added https://youri--c.cs22.visual.force.comto the remote Site settings in Salesforce but that still seem to be causing issues...
Any suggestions?
EDIT: I figured out the first part of my issue I needed to white list https://youri--c.cs22.visual.force.comin Remote Settings> CORS and not remote sites but I still get the Bad request error...
See the Edit:
EDIT: I figured out the first part of my issue I needed to white list https://youri--c.cs22.visual.force.comin Remote Settings> CORS and not remote sites but I still get the Bad request error...
The server side for my project provides WebApi 2.2
Client side is mobile application written in Ionic
Everything runs locally in chrome, mobile app in emulation mode.
1) On the server CORS is enabled and every API controller is decorated with:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
2) angular $http service is also configured to work with CORS:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.common['X-FirePHP-Version'];
3) After user authenticates itself, I'm sending back form API controller a cookie:
var cookie = new CookieHeaderValue("user-id", result.Entity.ToString());
cookie.Path = "/";
cookie.HttpOnly = true;
cookie.Secure = true;
response.Headers.AddCookies(new CookieHeaderValue[]{ cookie });
I can see this cookie in the response header:
Set-Cookie:user-id=306d5247-1d3b-4120-b412-6ce45105397a; path=/; secure; httponly
4) In WebApi pipeline I registered global DelegatingHandler to read cookies sent with requests
The strange thing, for me, is that when I do make POST call (this request is preflighted), then in delegating handler cookies collection is empty. While changing the method AcceptVerb (both on the controller and in javascript service) to GET fixes my problem and my cookie is present.
My js service is:
var setData= function (model) {
var deferred = $q.defer();
var url = stringHelper.format(endpoints.setData, sessionId);
var config = {
url: url,
method: 'POST',
data: {
name: model.name,
email: model.email
}
};
$http(config).then(function (result) {
deferred.resolve(true);
}, function (error) {
$log.debug(error);
deferred.reject(error);
});
return deferred.promise;
}
Important notice: Making POST calls to the same endpoint from Postman works correctly.
Does anyone have a similar problem?
Thanks
I finally figured it out:
1) after comparison of working GET request with failing POST, I noticed that GET wasn't preflighted with OPTIONS, while POST was
2) in the CORS definig materials I read that OPTIONS are not sending any cookies
As a resolution I added checking request method in my DelegatingHandler - so it's passing OPTIONS methods down into pipeline without checking for autentifiaction cookie.
Hope that will help someone :)
Here's my WebApi DelegatingHandler:
public class UserCookieHandler : DelegatingHandler
{
static public string ServerSessionId = "server-session-id";
static public string UserSessionId = "user-session-id";
const string LoginUri = "api/secured/login/login";
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string sessionId = string.Empty;
if (request.Method != HttpMethod.Options && !request.RequestUri.PathAndQuery.Contains(LoginUri))
{
string cookie = request.GetCookie(ServerSessionId);
if (cookie == null)
{
return request.CreateErrorResponse(HttpStatusCode.Forbidden, "Please log in");
}
else
{
sessionId = cookie;
try
{
Guid guid = Guid.Parse(sessionId);
}
catch (FormatException)
{
request.CreateErrorResponse(HttpStatusCode.BadRequest, "Please log in again");
}
}
request.Properties[ServerSessionId] = sessionId;
}
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
return response;
}
}