[英]Spring Security, REST basic authentication issue
在使用Spring的基本認證時,我遇到了與HTTP響應頭“Access-Control-Allow-Origin”相關的問題。 當我手動驗證時,如下面的代碼(我正在使用REST):
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json")
@ResponseStatus(value = HttpStatus.OK)
public void login(@RequestBody String body, HttpServletResponse response)
throws IOException {
try {
User user = gson.fromJson(body, User.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
usuario.getUsername(), usuario.getPassword());
authenticationManager.authenticate(token);
} catch (BadCredentialsException e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
一切正常,我收到以下HTTP響應:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
Content-Type: text/html;charset=utf-8
Content-Length: 951
Date: Fri, 17 May 2013 19:14:36 GMT
如您所見,響應中存在“Access-Control-Allow-Origin”。 這里一切都很好。 我可以在我的ajax調用中捕獲401錯誤。
但是當自動執行身份驗證時,如下面的代碼:
@RequestMapping(value = "/name", method = RequestMethod.POST, consumes = "application/json")
@PreAuthorize("hasRole('ROLE_CUSTOMER')")
public @ResponseBody String getName(HttpServletResponse response) throws IOException {
String json = null;
try {
User userSession = (User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
Customer customer = customerDao.getNameByUsername(userSession.getUsername());
json = gson.toJson(customer);
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
return json;
}
HTTP響應是:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 981
Date: Fri, 17 May 2013 19:41:08 GMT
響應中沒有“Access-Control-Allow-Origin”
Google Chrome控制台顯示以下錯誤:
Origin null is not allowed by Access-Control-Allow-Origin
我的ajax調用沒有返回401 Unauthorized錯誤,即使HTTP響應返回它(上面的響應),我收到一個未知錯誤。
我發現對於所有瀏覽器,我需要HTTP響應中的“Access-Control-Allow-Origin”,否則它們會產生某種靜默錯誤,我的ajax調用將失敗(無法捕獲401錯誤)。 實際上,javascript將無聲地失敗。 沒有“Access-Control-Allow-Origin”,XMLHttpRequest不接受HTTP響應。
如何讓Spring在HTTP響應中注入“Access-Control-Allow-Origin”以進行基本身份驗證?
這是我的Spring Security xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http create-session="stateless" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/customer/**" />
<security:http-basic />
<security:custom-filter ref="basicAuthenticationFilter"
after="BASIC_AUTH_FILTER" />
</security:http>
<bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="teste.com" />
</bean>
<!-- It is responsible for validating the user's credentials -->
<security:authentication-manager alias="authenticationManager">
<!-- It is responsible for providing credential validation to the AuthenticationManager -->
<security:authentication-provider>
<security:password-encoder ref="passwordEncoder" />
<security:jdbc-user-service
data-source-ref="mySQLdataSource"
users-by-username-query="select username, password, enabled from usuario where username = ?"
authorities-by-username-query="select username, papel from autoridade where username = ?" />
</security:authentication-provider>
</security:authentication-manager>
<bean class="org.springframework.security.crypto.password.StandardPasswordEncoder"
id="passwordEncoder" />
</beans>
剛剛找到了自己的方式:
首先,我真的不記得為什么我把這一行放在這里,但它弄亂了我的代碼:
<security:http-basic />
其次,這個答案告訴我路徑: 處理Spring Security中基本身份驗證的未經授權的錯誤消息 。 我必須創建一個自定義身份驗證入口點,以便發送Access-Control-Allow-Origin。
所以現在這是我的代碼:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http create-session="stateless"
entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/api/admin/**" />
<security:intercept-url pattern="/medico/**" />
<!-- <security:http-basic /> -->
<security:custom-filter ref="basicAuthenticationFilter"
after="BASIC_AUTH_FILTER" />
</security:http>
<bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
</bean>
<!--
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="test.com" />
</bean> -->
<bean id="authenticationEntryPoint"
class="com.test.util.PlainTextBasicAuthenticationEntryPoint">
<property name="realmName" value="test.com" />
</bean>
<!-- It is responsible for validating the user's credentials -->
<security:authentication-manager alias="authenticationManager">
<!-- It is responsible for providing credential validation to the AuthenticationManager -->
<security:authentication-provider>
<security:password-encoder ref="passwordEncoder" />
<security:jdbc-user-service
data-source-ref="mySQLdataSource"
users-by-username-query="select username, password, enabled from usuario where username = ?"
authorities-by-username-query="select username, papel from autoridade where username = ?" />
</security:authentication-provider>
</security:authentication-manager>
<bean
class="org.springframework.security.crypto.password.StandardPasswordEncoder"
id="passwordEncoder" />
</beans>
package com.test.util;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
public class PlainTextBasicAuthenticationEntryPoint extends
BasicAuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.addHeader("Access-Control-Allow-Origin", "null");
response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage());
}
}
我的http響應現在:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: null
WWW-Authenticate: Basic realm="test.com"
Content-Length: 35
Date: Mon, 20 May 2013 20:05:03 GMT
HTTP Status 401 - Bad credentials
在更改之前,我收到此錯誤消息:
OPTIONS http://localhost:8080/test/customer/name 200 (OK) jquery-1.8.2.min.js:2
XMLHttpRequest cannot load http://localhost:8080/test/customer/name. Origin null is not allowed by Access-Control-Allow-Origin.
現在我按照預期得到了這個:
OPTIONS http://localhost:8080/test/customer/name 200 (OK) jquery-1.8.2.min.js:2
POST http://localhost:8080/test/customer/name 401 (Unauthorized)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.