2017-04-04 119 views
0

我正在运行一个基于spring安全性4.2版本的弹簧mvc 4.2版的web应用程序。我想运行customAuthenticationProvidercustomAuthenticationSuccessHandler,但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); 
    } 
} 

回答

1

我认为,正在发生的事情是,在你的AuthenticationProvidersupports(Class<?> authentication)方法不正确实施。

你正在检查对你CustomAuthenticationProvidergetClass()方法收到了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(); 
      } 
     }