我正在使用 Spring 基本身份验证,在我的安全 xml 中具有以下设置:
<http use-expressions="true" create-session="never" >
<intercept-url pattern="/**" method="GET" access="isAuthenticated()" />
<intercept-url pattern="/**" method="POST" access="isAuthenticated()" />
<intercept-url pattern="/**" method="PUT" access="isAuthenticated()" />
<intercept-url pattern="/**" method="DELETE" access="isAuthenticated()" />
<http-basic />
</http>
如果身份验证失败,浏览器会弹出一个提示窗口来输入用户名和密码。有没有办法使该提示根本不弹出?
最有可能的是,用于身份验证失败的页面也受到保护。您可以尝试手动将失败页面设置为不受保护的页面,例如
<access-denied-handler error-page="/login.jsp"/>
䋰
<intercept-url pattern="/*login*" access="hasRole('ROLE_ANONYMOUS')"/>
或
<intercept-url pattern='/*login*' filters='none'/>
或者,您可以使用 HTTP 元素的 auto-config='true'
属性来为您修复此问题。在此处查看更多内容
我在浏览器中抛出的 REST API 登录对话框也遇到了同样的问题。正如您所说,当浏览器看到响应标头为
WWW-Authenticate: Basic realm="Spring Security Application
它将提示一个基本的身份验证对话框。对于基于REST API的登录,这并不理想。这是我是如何做到的。定义自定义身份验证入口点并在开始将标题设置为"基于表单"
response.setHeader("WWW-Authenticate", "FormBased");
应用程序上下文.xml配置如下
<security:http create-session="never" entry-point-ref="authenticationEntryPoint" authentication-manager-ref="authenticationManager">
<security:custom-filter ref="customRestFilter" position="BASIC_AUTH_FILTER" />
<security:intercept-url pattern="/api/**" access="ROLE_USER" />
</security:http>
<bean id="authenticationEntryPoint" class="com.tito.demo.workflow.security.RestAuthenticationEntryPoint">
</bean>
下面的自定义入口点类。
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static Logger logger = Logger.getLogger(RestAuthenticationEntryPoint.class);
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException ) throws IOException {
logger.debug("<--- Inside authentication entry point --->");
// this is very important for a REST based API login.
// WWW-Authenticate header should be set as FormBased , else browser will show login dialog with realm
response.setHeader("WWW-Authenticate", "FormBased");
response.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
}
}
注意:我用过弹簧 3.2.5.发布
现在,当 rest API 被像 POSTMAN 这样的 restclient 击中时,服务器将返回 401 Unauthorized。
我遇到了同样的问题,我所做的就是在我的资源服务器中创建自定义RequestMatcher
。这可以防止 Outh2 发送WWW-Authenticate header
。
例:
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OAuthRequestedMatcher())
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
}
private static class OAuthRequestedMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
boolean haveOauth2Token = (auth != null) && auth.startsWith("Bearer");
boolean haveAccessToken = request.getParameter("access_token")!=null;
return haveOauth2Token || haveAccessToken;
}
}