如何在 Grails 和 AngularJS 上使用 Spring Security 进行 Ajax 登录
Posted
技术标签:
【中文标题】如何在 Grails 和 AngularJS 上使用 Spring Security 进行 Ajax 登录【英文标题】:How to do Ajax login with Spring Security on Grails and AngularJS 【发布时间】:2015-12-30 20:13:58 【问题描述】:我正在尝试创建向服务器发送 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)
$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_username
和 j_password
并且总是返回带有状态 200
和错误文本 "error":"Sorry, we were not able to find a user with that username and password."
的响应
PS 我正在为 Grails (3.0.4) 使用 Spring Security 插件http://grails-plugins.github.io/grails-spring-security-core/guide/index.html
【问题讨论】:
【参考方案1】:所以这就是问题所在。 Spring Security 插件仅接受带有数据作为查询字符串的POST
请求,当我们通过 Angular 的 $http
调用在 POST 请求中传递一些数据时,它会在请求有效负载正文中发送数据,这会破坏登录,并且您会收到没有用户的消息找到了。
所以第一种方法是使用$http
将username
和password
作为params
传递:
$http(
method: 'POST',
url: '/j_spring_security_check',
params: j_username: credentials.username, j_password: credentials.password, ajax: true
)
上述方法可以正常工作,但问题是用户名和密码将在查询字符串中发送,因此任何人都可以轻松地在浏览器控制台中读取,因为它不受保护。此外,由于这将作为查询字符串参数传递,因此密码将被记录在各种级别,例如 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'
)
所以我们在这里所做的是将凭据作为发布数据发送,并以编程方式更改 Content-Type
,以便 Angular 可以将其作为发布数据而不是 JSON 发送。
注意:附加建议:Grails request
属性 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 区分每种类型的请求 :)以上是关于如何在 Grails 和 AngularJS 上使用 Spring Security 进行 Ajax 登录的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Angular js 集成到 grails 2.3.4 中?
AngularJS 和 Grails 中基于角色的用户身份验证
Grails、Spring Security 和 Angular JS - 如何保护 URL?
Grails - Ionic - AngularJS - 在这个环境中工作是个好主意吗?