自定义身份验证提供程序未被调用 Spring 安全
Custom Authentication Provider is not getting called Spring Security
我正在尝试实现自定义 AuthenticationProvider 来验证对我所有受保护的 URL 的调用。我已经实现了所有方法并相信我的 xml 配置是正确的,但是对受保护 URL 的调用总是转到入口点引用 class(我在此处抛出 401 错误)。这正在跳过我的身份验证提供程序(我的身份验证方法中有日志语句并且知道它没有被调用)。从其他帖子我了解到 supports 方法可能是罪魁祸首,但我将其设置为始终 return true 所以这不应该是我的问题。
我的安全上下文代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<security:http
use-expressions="true"
auto-config="false"
create-session="stateless"
entry-point-ref="unauthorizedEntryPoint"
authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/User/sign_up/*" access="permitAll" />
<security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="pathto:CustomAuthenticationProvider" />
<beans:bean id="unauthorizedEntryPoint" class="pathto:UnauthorizedEntryPoint" /
web.xml的代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/security-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
未经授权的入口点:
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authenticationException) throws IOException, ServletException {
System.out.println("in unauth");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failure: UnauthorizedEntryPoint Token invalid");
}
}
AuthenticationProvider:(当前未在此处进行任何身份验证)
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication auth)
throws AuthenticationException {
System.out.println("in authenticate");
String username = auth.getName();
String password = auth.getCredentials().toString();
List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
System.out.println("username: "+username+". password: "+ password);
if (true) { //checkPassword(password, user.getPasswords())) {
AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
}
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
更新:
我正在使用 Advanced Rest Client 使用参数 j_username 和 j_password 对此进行测试。这是正确的还是问题所在?
您是否了解可能出现的问题?
谢谢!
为什么不删除 security:http
下的 authentication-manager-ref
?您已经声明了 authentication-manager
标签。
<security:http
use-expressions="true"
auto-config="false"
create-session="stateless"
entry-point-ref="unauthorizedEntryPoint">
<security:intercept-url pattern="/User/sign_up/**" access="permitAll" />
<security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>
此外;不是你问题的一部分,只是建议:
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
您没有配置 Web 身份验证机制,因此无法调用身份验证管理器。因此,请求总是会到达您的身份验证入口点(为未经身份验证的用户调用)并且您会收到观察到的错误。通常,身份验证入口点会做一些事情,比如重定向到登录表单,或发送 WWW-Authenticate
header.
您需要配置表单或基本身份验证之类的东西(请参阅手册或项目附带的示例)。请注意,您还将应用程序配置为无状态,因此每个请求都需要进行身份验证。
我正在尝试实现自定义 AuthenticationProvider 来验证对我所有受保护的 URL 的调用。我已经实现了所有方法并相信我的 xml 配置是正确的,但是对受保护 URL 的调用总是转到入口点引用 class(我在此处抛出 401 错误)。这正在跳过我的身份验证提供程序(我的身份验证方法中有日志语句并且知道它没有被调用)。从其他帖子我了解到 supports 方法可能是罪魁祸首,但我将其设置为始终 return true 所以这不应该是我的问题。
我的安全上下文代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<security:http
use-expressions="true"
auto-config="false"
create-session="stateless"
entry-point-ref="unauthorizedEntryPoint"
authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/User/sign_up/*" access="permitAll" />
<security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="pathto:CustomAuthenticationProvider" />
<beans:bean id="unauthorizedEntryPoint" class="pathto:UnauthorizedEntryPoint" /
web.xml的代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/security-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
未经授权的入口点:
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authenticationException) throws IOException, ServletException {
System.out.println("in unauth");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failure: UnauthorizedEntryPoint Token invalid");
}
}
AuthenticationProvider:(当前未在此处进行任何身份验证)
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication auth)
throws AuthenticationException {
System.out.println("in authenticate");
String username = auth.getName();
String password = auth.getCredentials().toString();
List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
System.out.println("username: "+username+". password: "+ password);
if (true) { //checkPassword(password, user.getPasswords())) {
AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
}
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
更新: 我正在使用 Advanced Rest Client 使用参数 j_username 和 j_password 对此进行测试。这是正确的还是问题所在?
您是否了解可能出现的问题?
谢谢!
为什么不删除 security:http
下的 authentication-manager-ref
?您已经声明了 authentication-manager
标签。
<security:http
use-expressions="true"
auto-config="false"
create-session="stateless"
entry-point-ref="unauthorizedEntryPoint">
<security:intercept-url pattern="/User/sign_up/**" access="permitAll" />
<security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>
此外;不是你问题的一部分,只是建议:
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
您没有配置 Web 身份验证机制,因此无法调用身份验证管理器。因此,请求总是会到达您的身份验证入口点(为未经身份验证的用户调用)并且您会收到观察到的错误。通常,身份验证入口点会做一些事情,比如重定向到登录表单,或发送 WWW-Authenticate
header.
您需要配置表单或基本身份验证之类的东西(请参阅手册或项目附带的示例)。请注意,您还将应用程序配置为无状态,因此每个请求都需要进行身份验证。