没有名为' CustomAuthenticationProvider'被定义为

时间:2014-08-05 23:08:03

标签: java xml spring spring-mvc spring-security

我正在尝试从正在运行的jdbc-user-service切换到实现AuthenticationProvider的customAuthenticationProvider,但是spring没有找到它。我不确定它是否与在xml中使用我的配置或出了什么问题有关。我从我的调度程序servlet中开始使用一个,但是根据我读到的内容的建议,我在spring-security.xml中添加了一个,这没有任何区别。任何想法我的配置有什么问题?

谢谢!

MVC分派-servlet.xml中

 <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.mkyong.*" />
    <!-- Currently not working. Made a work around by having resources at /resources and pages at /pages -->
  <mvc:resources location="/resources/" mapping="/resources/" />

      <!-- also add the following beans to get rid of some exceptions -->
     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
     <bean
      class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
     </bean>

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix"><value>/WEB-INF/pages/</value></property>
        <property name="suffix"><value>.jsp</value></property>
    </bean>

</beans>

弹簧security.xml文件

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"  
    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-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd>

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <!-- login page must be available to all. The order matters, if this is after something which secures the page this will fail. -->
        <intercept-url pattern="/pages/login" access="permitAll" />
        <intercept-url pattern="/pages/admin/**" access="hasRole('_admin')" />
        <intercept-url pattern="/pages/trade/**" access="hasRole('_trader')" />
        <intercept-url pattern="/pages/discover/**" access="hasRole('_users')" />       
        <!-- access denied page -->
        <access-denied-handler error-page="/pages/403" />
        <form-login 
            login-page="/pages/login" 
            default-target-url="/pages/trade/index" 
            authentication-failure-url="/login?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-url="/pages/logout" logout-success-url="/pages/login?logout" />
        <!-- enable csrf protection -->
        <csrf/>
    </http>

    <!-- Select users and user_roles from database -->
    <authentication-manager>
        <authentication-provider ref="CustomAuthenticationProvider"/>
        <!--<jdbc-user-service data-source-ref="dataSource"
                users-by-username-query=
                    "select email,pwhash, enabled from users where email=?"
                authorities-by-username-query=
                    "select email, groupname from usergroups where email =?  " /> 
        </authentication-provider> -->
    </authentication-manager>  
</beans:beans>

CustomAuthenticationProvider.java

package com.mkyong.web.controller;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    User user = new User();
    user.name = authentication.getName();
    user.password = authentication.getCredentials().toString();
    try {
      user.id = Instance.users.getUserByEmail(user.name).getUserID();
    } catch (Exception e) {
      Instance.debug("CustomAuthenticationProvider authenticate","Error getting user" + e);
    }

    // use the credentials to try to authenticate against the third party system
    if (passVerify(user)) {
      List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
      try {
        UserRoles roles = Instance.users.getUser(user.id).roles;
        userRolesToDatabaseRoles(roles, grantedAuths);
      } catch (Exception e) {
        Instance.debug("CustomAuthenticationProvider authenticate","Error getting user" + e);
      }
      return new UsernamePasswordAuthenticationToken(user.name, user.password, grantedAuths);
    } else {
      Instance.debug("CustomAuthenticationProvider authenticate","Unable to authenticate");
      return null;
    }
  }

  private void userRolesToDatabaseRoles(UserRoles roles, List<GrantedAuthority> grantedAuths) {
    if(roles.admin){
      grantedAuths.add(new SimpleGrantedAuthority("_admin"));
    }
    if(roles.trader){
      grantedAuths.add(new SimpleGrantedAuthority("_trader"));
    }
    if(roles.analyst){
      grantedAuths.add(new SimpleGrantedAuthority("_users"));
    }


  }

  private boolean passVerify(User user) {
    StringBuffer MD5 = getMD5(user);    
    try {
      //User still has an MD5 password, so change them over to bcrypt
      if(MD5.toString().equals(Instance.users.getPasswordHash(user.name))){
        String hashedPassword = getBcrypt(user).toString();
        instance.users.changePassword(user.id, hashedPassword);
        return true;
      }
    } catch (Exception e) {
      instance.debug("CustomAuthenticationProvider passVerify","Error getting userpassword" + e);
    }

    StringBuffer bcrypt = getBcrypt(user);

    if(bcrypt.toString().equals(user.password)){
      return true;
    }



    return false;
  }

  public StringBuffer getBcrypt(User user) {
    //This sets how many rounds bcrypt will run. The high the number the longer it takes which will slow down user login, however it also slows
    //down a would be attacker. This is a key advantage of bcrypt over other algorithms. *IMPORTANT* changing the strength will result in needing to 
    //rehash all passwords. This is very doable but requires more work. 
    //See http://crypto.stackexchange.com/questions/3003/do-i-have-to-recompute-all-hashes-if-i-change-the-work-factor-in-bcrypt
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
    StringBuffer hashedPassword = new StringBuffer(); 
    hashedPassword.append(passwordEncoder.encode(user.password));

    return hashedPassword;
  }

  public StringBuffer getMD5(User user) {
    StringBuffer sb = null;
    MessageDigest md;

    String original = "a";
    try {
      md = MessageDigest.getInstance("MD5");
      md.update(original.getBytes());
      byte[] digest = md.digest();
      sb = new StringBuffer();
      for (byte b : digest) {
        sb.append(String.format("%02x", b & 0xff));
      }

    } catch (NoSuchAlgorithmException e) {
     instance.debug("CustomAuthenticationProvider hashMD5","Error getting MD5 instance" + e);
    }

    return sb;
  }


  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }

  public class User{
    public long id;
    protected String name, password;
  }



}

不确定是否需要发布web.xml,但这里是:

的web.xml

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


        <!-- Spring MVC -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

      <servlet>
    <servlet-name>InitServlet</servlet-name>
    <servlet-class>servletInitServlet</servlet-class>
    <init-param>
      <param-name>configfile</param-name>
      <param-value>C:/transmetric/dev/java/WebContent/WEB-INF/config.properties</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>AdminServlet</servlet-name>
    <servlet-class>servlet.admin</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>servlet.user</servlet-class>
    <load-on-startup>4</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>SignupUserServlet</servlet-name>
    <servlet-class>servlet.user.SignupUserServlet</servlet-class>
    <load-on-startup>5</load-on-startup>
  </servlet>

  <servlet>
   <servlet-name>ReceiveFile</servlet-name>
    <servlet-class>servlet.user</servlet-class>
    <load-on-startup>6</load-on-startup>
  </servlet>

  <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/pages/*</url-pattern>
    </servlet-mapping>

  <servlet-mapping>
   <servlet-name>AdminServlet</servlet-name>
   <url-pattern>/AdminServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>UserServlet</servlet-name>
   <url-pattern>/UserServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>SignupUserServlet</servlet-name>
   <url-pattern>/SignupUserServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>ReceiveFile</servlet-name>
   <url-pattern>/ReceiveFile</url-pattern>
  </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml,
            /WEB-INF/spring-database.xml
        </param-value>
    </context-param>

    <!-- Spring Security -->
    <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>

3 个答案:

答案 0 :(得分:2)

尝试在spring-security xml中定义CustomAuthenticationProvider bean,而不是使用@Component注释。

或者您也可以尝试将<context:component-scan base-package="com.mkyong.*" />放入安全xml

答案 1 :(得分:1)

更改

<authentication-provider ref="CustomAuthenticationProvider"/>

to(不是未大写的bean名称)

<authentication-provider ref="customAuthenticationProvider"/>

默认情况下,使用@Component注释的自动检测组件的bean名称是非大写的非限定类名。在您的情况下,这将是customAuthenticationProvider

答案 2 :(得分:0)

在我的情况下,由于Maven构建错误导致实际丢失public static bool IsAnagram(string firstString, string secondString) { firstString = firstString.Replace(" ", "").ToLower(); secondString = secondString.Replace(" ", "").ToLower(); var firstStringArray = firstString.OrderBy(x => x); var secondStringArray = secondString.OrderBy(x => x); string s1 = new string(firstStringArray.ToArray()); string s2 = new string(secondStringArray.ToArray()); if (s1.Equals(s2)) { return true; } else { return false; } } 文件导致异常:

  • .class
  • (YourApp)/target/classes
  • (YourApp)/target/(YourApp).war/WEB-INF/classes/

根本原因是Eclipse问题:它切换到使用嵌入式Maven,而我总是使用外部Maven。为了解决这个问题,我不得不:

  1. 偏好设置&gt; Maven&gt;安装,设置外部Maven
  2. 从工作区删除项目
  3. 删除项目文件夹中的所有派生文件/文件夹((YourApp)/target/(YourApp).war/WEB-INF/lib/target/bin/.settings/&amp; .classpath),仅保留{{1 }和.project
  4. 文件&gt;导入...&gt;现有的Maven项目,选择我的项目。
  5. 重建后,所有必需的课程都在那里。