没有 JSP 的 Spring Security /j_spring_security_check
Posted
技术标签:
【中文标题】没有 JSP 的 Spring Security /j_spring_security_check【英文标题】:Spring Security /j_spring_security_check without JSP 【发布时间】:2015-07-10 07:41:36 【问题描述】:我需要干净的 URL 而不是附加的扩展名。我在我的 UI 中使用 Backbone.js 框架。我构建了一个视图,它收集用户名和密码并对/j_spring_security_check
执行一个安静的请求。
由于某种原因,/j_spring_security_check
端点看不到用户名和密码。
这是我在主干中执行的请求:
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
发出请求的正确方法是什么?
【问题讨论】:
【参考方案1】:让我们看看 Spring 的执行身份验证的类,它是 /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());
当它需要一个 POST 请求时,您正在发送一个带有 /jspring_security_check?j_username=X&j_password=Z 的 GET 请求。
请求必须是带有 Content-Type 'application/x-www-form-urlencoded' 和两个参数的 POST 请求。请求正文不应是 JSON 对象。
我建议重新设计您的登录,不要使用 Ajax。
j_spring_security_check 并非设计为通过 Ajax 从登录页面调用。它旨在接受来自 html 表单的 POST 请求,然后在 HTTP 响应中呈现应用程序主页以提交登录表单。
j_spring_security_check 所做的是对用户进行身份验证,如果身份验证成功,它会创建一个会话并将用户重定向到主屏幕,否则它将用户重定向到“登录失败”屏幕。 j_spring_security_check 返回 302 HTTP 代码,这是一个重定向。
RESTful 登录是可能的,但您必须配置 j_spring_security_check 以不使用成功(或失败)登录视图进行响应,而是使用 JSON,因此您必须在 Java 端编写自定义登录处理程序。我做过一次,这使得代码(Java 和 ExtJS)变得如此复杂,以至于我退回到基于表单的登录。毕竟,Facebook 和 Google 使用表单提交登录,这很正常。在我的情况下,切换到 Ajax REST 登录是不值得的。
表单提交的另一个优点是网络浏览器可以记住登录名和密码,这是基于 Ajax 的登录无法做到的,我认为这就是 Google 和 Facebook 都使用表单提交的原因。
但是,如果您决定仍然需要基于 Ajax 的登录(由于实现的复杂性以及用户体验会因浏览器的密码管理器不工作而受到损害),那么您将不得不创建两个 Spring MVC 控制器,一个用于成功登录 (loginSucessController),另一个用于登录失败 (loginFailureController),两个控制器都应返回带有登录状态的统一 JSON 响应。然后配置 Spring Security 使用上面的两个控制器
<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 应该返回
"loginStatus": 1
并且 loginFailureController 应该返回
"loginStatus": 0
您还必须创建第三个 MVC 控制器来检测用户是否已经登录,以决定当用户返回应用程序网页时是否必须显示登录表单,请使用 org.springframework.security。 core.context.SecurityContextHolder#getContext
【讨论】:
我在使用 JSP 时遇到的问题是我的主干视图都使用 HTML 模板来构建 html 视图。因此,为了使用 JSP 页面,我必须构建没有主干的页面。我宁愿只使用主干框架构建整个应用程序。 在我使用骨干网时使用 JSP 登录表单的最佳方式是什么?是否可以将 jsp 嵌入到主干视图中? 当我使用 ExtJS 开发应用程序时,我创建了一个单独的静态 HTML 网页用于登录,它根本不使用 javascript。用户在成功登录后被重定向到 ExtJS 应用程序 html 文件,这是最简单的方法。以上是关于没有 JSP 的 Spring Security /j_spring_security_check的主要内容,如果未能解决你的问题,请参考以下文章
没有 Spring 标记库 (JSTL) 的 Spring Security
添加“spring-security-taglibs”后jsp中仍然报错:找不到spring security标签的标签库描述符