J'ai créé une démonstration utilisant JavaScript pour l'API de recherche de photos Flickr. Maintenant je le convertis en AngularJs . J'ai effectué une recherche sur Internet et trouvé la configuration ci-dessous.
Configuration:
myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Un service:
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.flickrPhotoSearch = function() {
return $http({
method: 'GET',
url: 'http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=3f807259749363aaa29c76012fa93945&tags=india&format=json&callback=?',
dataType: 'jsonp',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
Manette:
myApp.controller('flickrController', function($scope, dataService) {
$scope.data = null;
dataService.flickrPhotoSearch().then(function(dataResponse) {
$scope.data = dataResponse;
console.log($scope.data);
});
});
Mais j'ai quand même eu la même erreur ... Voici quelques liens que j'ai essayés:
XMLHttpRequest ne peut pas charger d'URL. Origine non autorisée par Access-Control-Allow-Origin
http://samurails.com/tutorial/cors-with-angular-js-and-sinatra/
MODIFIER:
J'ai créé un serveur proxy dans node.js sur la suggestion de @Quentin:
var http = require('http');
var url = require('url');
var fs = require('fs');
var server;
server = http.createServer(function (req, res) {
// your normal server code
var path = url.parse(req.url).pathname;
fs.readFile(__dirname + path, function (err, data) {
if (err) {
return send404(res);
}
res.writeHead(200, {'Content-Type':path == 'json.js' ? 'text/javascript' : 'text/html'});
res.write(data, 'utf8');
res.end();
});
}),
server.listen(8001);
//using express to load customizes static files
var express = require("express"),
app = express();
app.all("/api/*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
return next();
});
app.use("/js", express.static(__dirname + '/js'));
app.listen(3001);
Final Edit
J'ai enlevé l'en-tête d'autorisation
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
et il fonctionne bien. J'ai ce que je voulais ... Merci à tous pour votre participation à cette question
Vous pas. Le serveur auquel vous faites la demande doit implémenter CORS pour permettre à JavaScript d'accéder à votre site Web. Votre JavaScript ne peut pas s'accorder la permission d'accéder à un autre site.
J'ai eu un problème similaire et, pour moi, il s’est résenti à l’ajout des en-têtes HTTP suivants à la réponse de la destinataire :
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Vous préférerez peut-être ne pas utiliser le *
à la fin, mais uniquement le nom de domaine de l'hôte qui envoie les données. Comme *.example.com
Mais ceci n'est possible que lorsque vous avez accès à la configuration du serveur.
Essayez d’utiliser le service de ressources pour utiliser le jsonp de flickr:
var MyApp = angular.module('MyApp', ['ng', 'ngResource']);
MyApp.factory('flickrPhotos', function ($resource) {
return $resource('http://api.flickr.com/services/feeds/photos_public.gne', { format: 'json', jsoncallback: 'JSON_CALLBACK' }, { 'load': { 'method': 'JSONP' } });
});
MyApp.directive('masonry', function ($parse) {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-item', columnWidth: $parse(attrs.masonry)(scope) });
}
};
});
MyApp.directive('masonryItem', function () {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.imagesLoaded(function () {
elem.parents('.masonry').masonry('reload');
});
}
};
});
MyApp.controller('MasonryCtrl', function ($scope, flickrPhotos) {
$scope.photos = flickrPhotos.load({ tags: 'dogs' });
});
Modèle:
<div class="masonry: 240;" ng-controller="MasonryCtrl">
<div class="masonry-item" ng-repeat="item in photos.items">
<img ng-src="{{ item.media.m }}" />
</div>
</div>
Ce problème est dû à une stratégie de modèle de sécurité d'application Web définie sur Stratégie d'origine identique. En vertu de la stratégie, un navigateur Web permet aux scripts contenus dans une première page Web d'accéder aux données d'une deuxième page Web, mais uniquement si les deux pages Web ont la même origine. Cela signifie que le demandeur doit correspondre à l'hôte, au protocole et au port exact du site demandeur.
Nous avons plusieurs options pour résoudre ce problème d’en-tête CORS.
Using Proxy - Dans cette solution, nous allons exécuter un proxy tel que, lorsque la requête passe par le proxy, il apparaisse comme s'il s'agissait du même Origine . Si vous utilisez le nodeJS, vous pouvez utiliser cors-partout pour faire le travail de proxy. https://www.npmjs.com/package/cors-anywhere .
Exemple:-
var Host = process.env.Host || '0.0.0.0';
var port = process.env.PORT || 8080;
var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
originWhitelist: [], // Allow all origins
requireHeader: ['Origin', 'x-requested-with'],
removeHeaders: ['cookie', 'cookie2']
}).listen(port, Host, function() {
console.log('Running CORS Anywhere on ' + Host + ':' + port);
});
JSONP - JSONP est une méthode permettant d'envoyer des données JSON sans se soucier des problèmes inter-domaines. Il n'utilise pas l'objet XMLHttpRequest.Il utilise plutôt la balise <script>
. https://www.w3schools.com/js/js_json_jsonp.asp
Server Side - Sur le serveur, nous devons activer les requêtes d'origine croisée ..__ Nous allons tout d'abord obtenir les requêtes avec contrôle en amont (OPTIONS), puis autoriser la requête ayant le code d'état 200 (ok ).
Les demandes en amont envoient d’abord un en-tête de demande HTTP OPTIONS à la ressource de l’autre domaine, afin de déterminer si la demande réelle peut être envoyée en toute sécurité. Les requêtes intersites font l’objet d’un contrôle en amont de la sorte car elles peuvent avoir des conséquences sur les données de l’utilisateur. En particulier, une demande est soumise à un contrôle en amont si elle utilise des méthodes autres que GET ou POST. De même, si POST est utilisé pour envoyer des données de demande avec un type de contenu autre que application/x-www-form-urlencoded, multipart/form-data ou text/plain, par exemple. si la demande POST envoie une charge XML au serveur à l'aide de application/xml ou text/xml, la demande est contrôlée en amont . Elle définit des en-têtes personnalisés dans la demande (par exemple, la demande utilise un en-tête tel que X -PINGOTHER)
Si vous utilisez le spring, il vous suffit de rajouter le code ci-dessous pour résoudre le problème… .. Ici, j'ai désactivé le jeton csrf qui n'a pas d'importance activer/désactiver selon vos besoins.
@SpringBootApplication
public class SupplierServicesApplication {
public static void main(String[] args) {
SpringApplication.run(SupplierServicesApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
}
Si vous utilisez la sécurité à ressort, utilisez le code ci-dessous avec le code ci-dessus.
@Configuration
@EnableWebSecurity
public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/**").authenticated().and()
.httpBasic();
}
}
Répondu par moi-même.
CORS angulaire js + restEasy on POST
Enfin, je suis arrivé à cette solution de contournement: La raison pour laquelle cela a fonctionné avec IE est que IE envoie directement un POST au lieu d’une demande de contrôle en amont pour demander une permission . Mais je ne sais toujours pas pourquoi le filtre n'a pas été en mesure de gérer une requête OPTIONS et envoie par défaut des en-têtes qui ne sont pas décrits dans le filtre (cela semble être une substitution pour ce seul cas ... peut-être une chose restEasy .. .)
J'ai donc créé un chemin OPTIONS dans mon service de repos qui réécrit la réponse et inclut les en-têtes dans la réponse à l'aide de l'en-tête de réponse.
Je cherche toujours le moyen propre de le faire si quelqu'un a déjà fait face à cela.
J'ai rencontré un problème similaire comme celui-ci, le problème était lié au backend. J'utilisais un serveur de noeud (Express). J'ai eu une requête get du frontend (angulaire) comme indiqué ci-dessous
onGetUser(){
return this.http.get("http://localhost:3000/user").pipe(map(
(response:Response)=>{
const user =response.json();
return user;
}
))
}
Mais cela a donné l'erreur suivante
Ceci est le code backend écrit en utilisant express sans les en-têtes
app.get('/user',async(req,res)=>{
const user=await getuser();
res.send(user);
})
Après avoir ajouté un en-tête à la méthode, le problème a été résolu.
app.get('/user',async(req,res)=>{
res.header("Access-Control-Allow-Origin", "*");
const user=await getuser();
res.send(user);
})
Vous pouvez obtenir plus de détails sur Activation de CORS sur Node JS
Apache/HTTPD a tendance à être présent dans la plupart des entreprises ou si vous utilisez Centos/etc chez vous. Donc, si vous avez cela en main, vous pouvez très facilement créer un proxy pour ajouter les en-têtes CORS nécessaires.
J'ai un article de blog à ce sujet ici car j'en ai souffert plusieurs fois récemment. Mais l’important, c’est d’ajouter ceci à votre fichier /etc/httpd/conf/httpd.conf et d’assurer que vous êtes déjà en train de faire "Listen 80":
<VirtualHost *:80>
<LocationMatch "/SomePath">
ProxyPass http://target-ip:8080/SomePath
Header add "Access-Control-Allow-Origin" "*"
</LocationMatch>
</VirtualHost>
Cela garantit que toutes les demandes d'URL sous votre-server-ip-server: 80/SomePath route vers http: // target-ip: 8080/SomePath (l'API sans support CORS) et qu'elles renvoient avec le code d'accès correct En-tête Control-Allow-Origin pour leur permettre de travailler avec votre application Web.
Bien sûr, vous pouvez modifier les ports et cibler l’ensemble du serveur plutôt que SomePath si vous le souhaitez.
var result=[];
var app = angular.module('app', []);
app.controller('myCtrl', function ($scope, $http) {
var url="";// your request url
var request={};// your request parameters
var headers = {
// 'Authorization': 'Basic ' + btoa(username + ":" + password),
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json; charset=utf-8',
"X-Requested-With": "XMLHttpRequest"
}
$http.post(url, request, {
headers
})
.then(function Success(response) {
result.Push(response.data);
$scope.Data = result;
},
function Error(response) {
result.Push(response.data);
$scope.Data = result;
console.log(response.statusText + " " + response.status)
});
});
And also add following code in your WebApiConfig file
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
we can enable CROS in frontend by using ngResourse module.
But most importantly, we should have this piece of code while making ajax
request in the controller,
$ scope.weatherAPI = $ resource (VOTRE API, {callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}}); $ scope.weatherResult = $ scope.weatherAPI.get (VOS DONNÉES DE DEMANDE, le cas échéant);
and not to mention, to add ngResourse CDN in script part and add as a dependecy
in app module.
<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>
then use "ngResourse" in app module dependency section like,
var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);