弹簧安全性定制认证不起作用
我正在运行一个基于spring安全性4.2版本的弹簧mvc 4.2版的web应用程序。我想运行customAuthenticationProvider和customAuthenticationSuccessHandler,但customAuthenticationProvider类是没有得到调用,请求将会只认证失败的URL弹簧安全性定制认证不起作用
的pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- Spring Security Jars starts-->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- Spring Security Jars ends-->
应用-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/resources/css/**" security="none"/>
<http pattern="/resources/img/**" security="none"/>
<http pattern="/resources/js/**" security="none"/>
<http auto-config="false" use-expressions="true">
<!-- <intercept-url pattern="/onemoretime/*" access="hasRole('ROLE_ADMIN')"/>-->
<intercept-url pattern="/admin/*" access="permitAll"/>
<intercept-url pattern="/vendor/*" access="permitAll"/>
<form-login login-page="/login"
username-parameter="username"
password-parameter="password"
authentication-success-handler-ref="customAuthenticationSuccessHandler"
authentication-failure-url="/accessdenied"
/>
<!-- <logout logout-success-url="/login"/> -->
<csrf />
</http>
<authentication-manager alias="authenticationProvider">
<authentication-provider ref="myAuthenticationProvider"/>
</authentication-manager>
<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="myAuthenticationProvider" class="com.opstree.vendorportal.authentication.CustomAuthenticationProvider"/>
<beans:bean id="customAuthenticationSuccessHandler" class="com.opstree.vendorportal.authentication.CustomAuthenticationSuccess"/>
</beans:beans>
的web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/service.xml /WEB-INF/application-security.xml</param-value>
</context-param>
<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>
loginpage.jsp
<form action="${pageContext.request.contextPath}/login" method="post">
<table>
<tr>
<td>UserName</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password"> </td>
</tr>
<tr>
<td align="center" colspan="2">
<div style="color:red" class="servererror">
<c:if test="${not empty userobject}">
<b><c:out value="${userobject.message}"></c:out></b>
</c:if>
</div>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" value="Login">
</td>
</tr>
<tr>
<td align="center" colspan="2">
<b><a href="forgotpassword">ForgotPassword</a></b>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<b>Click here to <a href="registerVendor">Register</a></b>
</td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
customAuthenticationProvider
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDBOperationsImpl userDAO;
private Logger logger = Logger.getLogger(getClass());
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println("Spring Security: Entered");
UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
String username = authenticationToken.getName();
//String password = (String) authenticationToken.getCredentials();
UserBean userBean = null;
try {
userBean = userDAO.getUserDetails(username);
} catch (Exception e) {
logger.error(e.getCause().getMessage());
}
if(userBean == null){
throw new BadCredentialsException("Invalid Credentials");
}
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(userBean, userBean.getPassword(), authorities);
System.out.println("Exit");
return auth;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(getClass());
}
立方米stomAuthenticationSuccess
public class CustomAuthenticationSuccess implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
throws IOException, ServletException {
System.out.println("Entered Authentication Successful Method");
boolean isUser = false;
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
String targetUrl = null;
for(GrantedAuthority currentAuth : authorities){
if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
isUser = true;
break;
}
else {
throw new IllegalStateException();
}
}
if(isUser){
targetUrl = "/vendor";
}
System.out.println("Entered Authentication Successful Method");
redirectStrategy.sendRedirect(request, response, targetUrl);
}
}
我认为,正在发生的事情是,在你的AuthenticationProvider
的supports(Class<?> authentication)
方法不正确实施。
你正在检查对你CustomAuthenticationProvider
getClass()
方法收到了Authentication
类,所以它永诺将返回false时,AuthenticationManager
将无法识别您的供应商作为一个合适的提供者收到的UsernamePasswordAuthenticationToken
。
您可以检查在github上org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider代码在那里你可以看到,在UsernamePasswordAuthenticationToken
配套供应商,此方法的正确实施应该是这样的:
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication));
}
我猜是实际发生的是,AuthenticationManager
不能找到一个UsernamePasswordAuthenticationToken
支持提供商,所以认证不能执行,并且未经授权的Authentication
正在到达UsernamePasswordAuthenticationFilter
,它最终无所事事,但是重定向到authentication-failure-url
。
要当心过你AuthenticationSuccessHandler
,正在检查的GranthedAuthorities
可能与评估的情况下,第一GranthedAuthority
一个IllegalStateException
结束的方式是不ROLE_USER
一个:
for(GrantedAuthority currentAuth : authorities){
if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
isUser = true;
break;
}
else {
throw new IllegalStateException();
}
}