如何在Grails和AngularJS上使用Spring安全性进行Ajax登录
我试图创建一个用户表单,将Ajax请求发送到服务器进行登录 Angular中的POST函数如下所示:如何在Grails和AngularJS上使用Spring安全性进行Ajax登录,ajax,angularjs,spring,grails,spring-security,Ajax,Angularjs,Spring,Grails,Spring Security,我试图创建一个用户表单,将Ajax请求发送到服务器进行登录 Angular中的POST函数如下所示: $http({ method: 'POST', url: '/j_spring_security_check', data: {j_username: credentials.username, j_password: credentials.password}, params: {ajax: true} }) .then(function (data)
$http({
method: 'POST',
url: '/j_spring_security_check',
data: {j_username: credentials.username, j_password: credentials.password},
params: {ajax: true}
})
.then(function (data) {
$rootScope.authenticated = false;
callback && callback();
},
function (error) {
$log.error("Error in login! " + JSON.stringify(error));
$rootScope.authenticated = false;
callback && callback();
});
在application.yml中,我得到了Spring Security的以下配置:
grails:
plugin:
springsecurity:
userLookup:
userDomainClassName: xxx.LoginUser
rejectIfNoRule: true
fii:
rejectPublicInvocations: false
controllerAnnotations:
staticRules:
[...]
当我调用函数并将请求发送到服务器时,就会出现问题。Spring Security不接受mu j_用户名和j_密码,并始终返回状态为200的响应和错误文本{错误:抱歉,我们无法找到具有该用户名和密码的用户。}
PS
我正在为Grails 3.0.4使用Spring安全插件,所以问题出在这里。Spring安全插件只接受以数据作为查询字符串的POST请求,当我们通过Angular的$http调用传递POST请求中的一些数据时,它会在请求有效负载体中发送数据,这会中断登录,您会收到未找到用户的消息 因此,第一种方法是使用$http将用户名和密码作为参数传递: 上述方法可以正常工作,但问题是用户名和密码将在查询字符串中发送,因此任何人都可以在浏览器控制台中轻松读取,因为它不受保护。此外,由于该密码将作为查询字符串参数传递,因此将在不同级别记录密码,如Tomcat的localhost日志或Nginx日志 要解决此问题,请按以下方式更改代码:
var data = 'j_username=' + credentials.username + '&j_password=' + credentials.password;
$http({
method: 'POST',
url: '@/j_spring_security_check',
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
因此,我们在这里所做的是将凭证作为post数据发送,并以编程方式更改内容类型,以便Angular可以将其作为post数据而不是JSON发送
注意:另外一个建议是:Grails request attribute request.xhr不会告诉您通过Angular的请求是AJAX请求,因为Angular不会发送任何请求头,以使其像用于Grails的AJAX一样工作。因此,添加以下代码:
var myApp = angular.module('myApp', []); // Or whatever your app name is
myApp.run(['$http', function ($http) {
$http.defaults.headers.common['x-requested-with'] = 'XMLHttpRequest';
}]);
现在,您不必在Angular$http调用中传递ajax:true。感谢关于xhr属性的说明,我正是在研究这个问题。很高兴知道这是预期的行为,我将添加标头,以便让Grails区分每种类型的请求:
var myApp = angular.module('myApp', []); // Or whatever your app name is
myApp.run(['$http', function ($http) {
$http.defaults.headers.common['x-requested-with'] = 'XMLHttpRequest';
}]);