根据凯文的建议,
阅读这篇文章后:1 https://stackoverflow.com/questions/14829825/custom-spring-3-0-security-filters-multiple-entrypoints-authenticationprovider, 2 https://stackoverflow.com/questions/7384842/usernamepasswordauthenticationfilter-problem、文档3 http://docs.spring.io/spring-security/site/docs/3.0.x/reference/ns-config.html,并感谢this http://beansgocrazy.blogspot.it/2011/07/custom-authentication-with-spring.html博客文章,
我编写了自己的 FORM_LOGIN_FILTER 来在身份验证之前直接管理 JSON。
我将我的代码粘贴到社区。
目标是同时授予经典浏览器表单 POST 身份验证和基于 JSON 的身份验证。另外,在 JSON 身份验证中,我想避免重定向到 loginSuccesful.htm
在上下文中:
<security:http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">
<security:intercept-url pattern="/logs/**" access="denyAll" />
<!-- ... All other intercept URL -->
<security:custom-filter ref="CustomUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER "/>
<security:logout
invalidate-session="true"
logout-success-url="/LogoutSuccessful.htm"
delete-cookies="true"
/>
<security:session-management>
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</security:session-management>
<security:access-denied-handler error-page="/accessDenied.htm" />
</security:http>
<bean id="CustomUsernamePasswordAuthenticationFilter" class="path.to.CustomUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="customSuccessHandler"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
<property name="usernameParameter" value="j_username"/>
<property name="passwordParameter" value="j_password"/>
</bean>
<bean id="customSuccessHandler" class="path.to.CustomAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/login.htm" />
<property name="targetUrlParameter" value="/LoginSuccessful.htm" />
</bean>
<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.htm" />
</bean>
<bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
自定义用户名密码验证过滤器类:
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
private String jsonUsername;
private String jsonPassword;
@Override
protected String obtainPassword(HttpServletRequest request) {
String password = null;
if ("application/json".equals(request.getHeader("Content-Type"))) {
password = this.jsonPassword;
}else{
password = super.obtainPassword(request);
}
return password;
}
@Override
protected String obtainUsername(HttpServletRequest request){
String username = null;
if ("application/json".equals(request.getHeader("Content-Type"))) {
username = this.jsonUsername;
}else{
username = super.obtainUsername(request);
}
return username;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
if ("application/json".equals(request.getHeader("Content-Type"))) {
try {
/*
* HttpServletRequest can be read only once
*/
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null){
sb.append(line);
}
//json transformation
ObjectMapper mapper = new ObjectMapper();
LoginRequest loginRequest = mapper.readValue(sb.toString(), LoginRequest.class);
this.jsonUsername = loginRequest.getUsername();
this.jsonPassword = loginRequest.getPassword();
} catch (Exception e) {
e.printStackTrace();
}
}
return super.attemptAuthentication(request, response);
}
}
自定义 AuthenticationSuccessHandler 类:
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication auth
)throws IOException, ServletException {
if ("application/json".equals(request.getHeader("Content-Type"))) {
/*
* USED if you want to AVOID redirect to LoginSuccessful.htm in JSON authentication
*/
response.getWriter().print("{\"responseCode\":\"SUCCESS\"}");
response.getWriter().flush();
} else {
super.onAuthenticationSuccess(request, response, auth);
}
}
}