Spring 安全 /j_spring_security_check 无 JSP
Spring Security /j_spring_security_check without JSP
我需要干净的 URL 而不是附加的扩展名。我在 UI 中使用 Backbone.js 框架。我构建了一个视图,该视图收集用户名和密码并向 /j_spring_security_check
执行 restful 请求。
由于某种原因,/j_spring_security_check
端点看不到用户名和密码。
这是我在 backbone 中执行的请求:
loginModel.save( loginModel.toJSON(), {
success: _.bind(function(response) {
Backbone.history.navigate('', {trigger: true});
}, this),
error: function() {
console.log('test');
}
});
我尝试使用 j_username 和 j_password 作为模型的属性发出请求,并将 url 设置为 /j_spring_security_check
。
我也试过直接在 url 中传递参数:
/jspring_security_check?j_username=X&j_password=Z
两种方式都进入我的身份验证提供程序身份验证方法,但 Credentials 和 Principal 都是空白字符串,因此身份验证失败。
当我发出请求时,我可以在浏览器的开发人员工具中看到请求负载被设置下来:
{j_username: "a", j_password: "a"} j_password: "a" j_username: "a"
在不使用 JSP 表单的情况下向 /j_spring_security_check
发出请求的正确方法是什么?
让我们看看 Spring 的 class 执行身份验证
/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java
private boolean postOnly = true;
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
您正在发送带有 /jspring_security_check?j_username=X&j_password=Z 的 GET 请求,而它需要 POST 请求。
请求必须是具有内容类型 'application/x-www-form-urlencoded' 和两个参数的 POST 请求。请求的主体不应是 JSON 对象。
我建议重新设计您的登录名,不要使用 Ajax。
j_spring_security_check 并非旨在通过 Ajax 从登录页面调用。它旨在接受来自 HTML 表单的 POST 请求,然后在登录表单提交的 HTTP 响应中呈现应用程序主页。
j_spring_security_check 所做的是对用户进行身份验证,如果身份验证成功,它会创建一个会话并将用户重定向到主屏幕,否则会将用户重定向到 "login failed" 屏幕。 j_spring_security_check returns 302 HTTP 代码是重定向。
RESTful 登录是可能的,但您必须配置 j_spring_security_check 以不使用成功(或失败)登录视图来响应,而是使用 JSON,因此您将拥有在 Java 端编写自定义登录处理程序。我这样做过一次,这让代码(Java 和 ExtJS)变得如此复杂,以至于我又回到了基于表单的登录。毕竟,Facebook 和 Google 使用表单提交登录,这很正常。在我的例子中,切换到 Ajax REST 登录是不值得的。
表单提交的另一个优点是 Web 浏览器可以记住登录名和密码,这是基于 Ajax 的登录不可能的,我认为这就是为什么 Google 和Facebook 使用表单提交。
但是如果您决定仍然需要基于 Ajax 的登录(我强烈反对这样做,因为实施起来很复杂,而且浏览器的密码管理器无法正常工作不会影响用户体验),那么您将不得不创建两个 Spring MVC 控制器,一个用于成功登录 (loginSucessController),另一个用于登录失败 (loginFailureController),两个控制器都应该 return 具有登录状态的统一 JSON 响应。然后配置Spring安全使用上面的两个控制器
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<sec:http>
<sec:intercept-url pattern="/**"/>
<sec:http-basic/>
<sec:form-login default-target-url="/loginSucessController" authentication-failure-url="/loginFailureController"/>
<sec:logout/>
</sec:http>
</beans>
当然,您必须为 loginSucessController 和 loginFailureController 创建映射和实现,我跳过了那部分。
loginSucessController 应该 return
{ "loginStatus": 1 }
并且 loginFailureController 应该 return
{ "loginStatus": 0 }
您还必须创建第三个 MVC 控制器来检测用户是否已经登录,以决定当用户 return 返回应用程序网页时是否必须显示登录表单,使用 org.springframework.security.core.context.SecurityContextHolder#getContext
我需要干净的 URL 而不是附加的扩展名。我在 UI 中使用 Backbone.js 框架。我构建了一个视图,该视图收集用户名和密码并向 /j_spring_security_check
执行 restful 请求。
由于某种原因,/j_spring_security_check
端点看不到用户名和密码。
这是我在 backbone 中执行的请求:
loginModel.save( loginModel.toJSON(), {
success: _.bind(function(response) {
Backbone.history.navigate('', {trigger: true});
}, this),
error: function() {
console.log('test');
}
});
我尝试使用 j_username 和 j_password 作为模型的属性发出请求,并将 url 设置为 /j_spring_security_check
。
我也试过直接在 url 中传递参数:
/jspring_security_check?j_username=X&j_password=Z
两种方式都进入我的身份验证提供程序身份验证方法,但 Credentials 和 Principal 都是空白字符串,因此身份验证失败。
当我发出请求时,我可以在浏览器的开发人员工具中看到请求负载被设置下来:
{j_username: "a", j_password: "a"} j_password: "a" j_username: "a"
在不使用 JSP 表单的情况下向 /j_spring_security_check
发出请求的正确方法是什么?
让我们看看 Spring 的 class 执行身份验证 /org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java
private boolean postOnly = true;
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
您正在发送带有 /jspring_security_check?j_username=X&j_password=Z 的 GET 请求,而它需要 POST 请求。
请求必须是具有内容类型 'application/x-www-form-urlencoded' 和两个参数的 POST 请求。请求的主体不应是 JSON 对象。
我建议重新设计您的登录名,不要使用 Ajax。
j_spring_security_check 并非旨在通过 Ajax 从登录页面调用。它旨在接受来自 HTML 表单的 POST 请求,然后在登录表单提交的 HTTP 响应中呈现应用程序主页。
j_spring_security_check 所做的是对用户进行身份验证,如果身份验证成功,它会创建一个会话并将用户重定向到主屏幕,否则会将用户重定向到 "login failed" 屏幕。 j_spring_security_check returns 302 HTTP 代码是重定向。
RESTful 登录是可能的,但您必须配置 j_spring_security_check 以不使用成功(或失败)登录视图来响应,而是使用 JSON,因此您将拥有在 Java 端编写自定义登录处理程序。我这样做过一次,这让代码(Java 和 ExtJS)变得如此复杂,以至于我又回到了基于表单的登录。毕竟,Facebook 和 Google 使用表单提交登录,这很正常。在我的例子中,切换到 Ajax REST 登录是不值得的。
表单提交的另一个优点是 Web 浏览器可以记住登录名和密码,这是基于 Ajax 的登录不可能的,我认为这就是为什么 Google 和Facebook 使用表单提交。
但是如果您决定仍然需要基于 Ajax 的登录(我强烈反对这样做,因为实施起来很复杂,而且浏览器的密码管理器无法正常工作不会影响用户体验),那么您将不得不创建两个 Spring MVC 控制器,一个用于成功登录 (loginSucessController),另一个用于登录失败 (loginFailureController),两个控制器都应该 return 具有登录状态的统一 JSON 响应。然后配置Spring安全使用上面的两个控制器
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<sec:http>
<sec:intercept-url pattern="/**"/>
<sec:http-basic/>
<sec:form-login default-target-url="/loginSucessController" authentication-failure-url="/loginFailureController"/>
<sec:logout/>
</sec:http>
</beans>
当然,您必须为 loginSucessController 和 loginFailureController 创建映射和实现,我跳过了那部分。
loginSucessController 应该 return
{ "loginStatus": 1 }
并且 loginFailureController 应该 return
{ "loginStatus": 0 }
您还必须创建第三个 MVC 控制器来检测用户是否已经登录,以决定当用户 return 返回应用程序网页时是否必须显示登录表单,使用 org.springframework.security.core.context.SecurityContextHolder#getContext