2016-07-22 149 views
0

我試圖將下面的spring security java配置轉換爲xml配置;面向Spring Security的XML配置問題

Java config;

package com.careapple.webservice.security.config; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.http.HttpMethod; 
import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.config.http.SessionCreationPolicy; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 
import org.springframework.security.web.AuthenticationEntryPoint; 
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 

import com.careapple.webservice.security.filter.AuthenticationTokenFilter; 

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@EnableTransactionManagement 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 
    @Autowired 
    private AuthenticationEntryPoint authenticationEntryPoint; 


    @Autowired 
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 
     authenticationManagerBuilder 
       .userDetailsService(userDetailsService) 
       .passwordEncoder(new BCryptPasswordEncoder()); 
    } 

    @Bean 
    @Override 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 


    @Bean 
    public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { 
     AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter(); 
     authenticationTokenFilter.setAuthenticationManager(super.authenticationManagerBean()); 
     return authenticationTokenFilter; 
    } 


    @Override 
    protected void configure(HttpSecurity httpSecurity) throws Exception { 
     httpSecurity 
       .csrf() 
       .disable() 
       .exceptionHandling() 
       .authenticationEntryPoint(authenticationEntryPoint) 
       .and() 
       .sessionManagement() 
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authorizeRequests() 
       .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 
       .antMatchers("/auth/**").permitAll() 
       .anyRequest().authenticated(); 

     // Custom JWT based authentication 
     httpSecurity 
       .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 
    } 
} 

轉換後的xml配置;彈簧security.xml文件

<?xml version="1.0" encoding="UTF-8"?> 
<bean:beans 
    xmlns:bean="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:c="http://www.springframework.org/schema/c" 
    xmlns="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-4.0.xsd"> 

    <global-method-security secured-annotations="enabled"/> 

    <http realm="Protected API" 
     create-session="stateless" 
     entry-point-ref="authenticationEntryPoint" 
     authentication-manager-ref="authenticationManager"> 

     <csrf disabled="true"/> 

     <custom-filter ref="authenticationTokenFilter" position="FORM_LOGIN_FILTER"/> 

     <intercept-url pattern="/login/**" access="permitAll"/> 
     <intercept-url pattern="/" access="isFullyAuthenticated()"/> 
    </http> 


    <bean:bean id="authenticationEntryPoint" class="com.careapple.webservice.security.EntryPointUnauthorizedHandler"/> 

    <bean:bean id="userDetailService" class="com.careapple.webservice.security.service.UserDetailsServiceImpl"/> 

    <bean:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> 

    <authentication-manager id="authenticationManager"> 
     <authentication-provider user-service-ref="userDetailService"> 
      <password-encoder ref="bcryptEncoder"></password-encoder> 
     </authentication-provider> 
    </authentication-manager> 

    <bean:bean id="authenticationTokenFilter" class="com.careapple.webservice.security.filter.AuthenticationTokenFilter" 
     c:authenticationManager-ref="authenticationManager"/> 

</bean:beans> 

我是新來的春季安全,我想第一件事是,有我轉換了Java配置正確XML。或者我錯過了什麼。

接下來,如果我運行這個XML文件的應用程序,我收到以下錯誤;

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property 'sourceList' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#0': Cannot resolve reference to bean 'authenticationTokenFilter' while setting constructor argument with key [3]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationTokenFilter' defined in ServletContext resource [/WEB-INF/spring-security.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities) 

其中,authenticationTokenFilter是,我使用的是自定義過濾器,它實現了Spring的UsernamePasswordAuthenticationFilter。

這是我的web.xml文件;

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
    id="WebApp_ID" version="3.0"> 

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

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

    <servlet> 
     <servlet-name>spring</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/spring-servlet.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

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

    <filter> 
     <filter-name>authenticationTokenFilter</filter-name> 
     <filter-class>com.careapple.webservice.security.filter.AuthenticationTokenFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>authenticationTokenFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

</web-app> 

我想太多的東西,現在, 1.是否所有的配置XML文件是正確的。 2.如果是這樣如何糾正我得到的異常。

請給出您的建議,我很長時間以來一直在努力。我提到了所有相關的stackoverflow問題,但我無法從中找到解決方案。

編輯: 這是我的AuthenticationTokenFilter;

package com.careapple.webservice.security.filter; 

import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 
import org.springframework.web.context.support.WebApplicationContextUtils; 

import com.careapple.webservice.security.TokenUtils; 
import com.careapple.webservice.util.AppConstant; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter { 

    @Autowired 
    private TokenUtils tokenUtils; 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException{ 

     tokenUtils = WebApplicationContextUtils 
       .getRequiredWebApplicationContext(this.getServletContext()) 
       .getBean(TokenUtils.class); 
     userDetailsService = WebApplicationContextUtils 
       .getRequiredWebApplicationContext(this.getServletContext()) 
       .getBean(UserDetailsService.class); 

     HttpServletResponse resp = (HttpServletResponse) response; 
     resp.setHeader("Access-Control-Allow-Origin", "*"); 
     resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH"); 
     resp.setHeader("Access-Control-Max-Age", "3600"); 
     resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, " + AppConstant.tokenHeader); 


     HttpServletRequest httpRequest = (HttpServletRequest) request; 
     String authToken = httpRequest.getHeader(AppConstant.tokenHeader); 
     System.out.println("Token: " + authToken); 
     String username = this.tokenUtils.getUsernameFromToken(authToken); 
     System.out.println("Username: " + username); 

     if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 
      UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 
      System.out.println("inside first if"); 
      if (this.tokenUtils.validateToken(authToken, userDetails)) { 
        UsernamePasswordAuthenticationToken authentication = 
          new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); 
        SecurityContextHolder.getContext().setAuthentication(authentication); 

      } 
     } 

      try { 
       chain.doFilter(request, response); 
      } catch (Exception e) { 
       Map<String, String> tokenExpired = new HashMap<>(); 
       tokenExpired.put("TokenExpired", "Authentication token expired, please login again"); 
       resp.setContentType("application/json"); 
       resp.setStatus(HttpStatus.FORBIDDEN.value()); 
       resp.getWriter().write(convertObjectToJson(tokenExpired)); 
      } 
    } 

    public String convertObjectToJson(Object object) throws JsonProcessingException { 
     if (object == null) { 
      return null; 
     } 
     ObjectMapper mapper = new ObjectMapper(); 
     return mapper.writeValueAsString(object); 
    } 
} 
+0

1.沒有事實並非如此。 2.使您的自定義篩選器成爲Spring安全篩選器鏈的一部分,而不是純文件運行web.xml。此外,爲什麼你想要XML配置,而不是基於Java的?其他方式更常見。 –

+0

感謝您的回覆,我是春季安全新手,請您告訴我們如何製作彈簧安全濾網鏈條的定製過濾部分。我不能夠使用託管服務器的Java配置,它給了我404,這就是爲什麼我改變了我的配置XML生活中的應用。我甚至發佈了這些問題,但無法從中獲得解決方案; http://stackoverflow.com/questions/38507424/mixing-xml-and-java-config-for-spring-security – karthi

+0

http://stackoverflow.com/questions/38482009/getting-404-when-deploying-spring- mvc-web-application-live-serverarvixe – karthi

回答

0

您的自定義認證過濾器需要僅在彈簧security.xml文件中定義,看着它,它應該是罰款。

在你的web.xml,你需要刪除你的過濾器(這是一個Spring Security的過濾器不是一個JavaEE的過濾器),並添加春季安全過濾器。來自Spring的錯誤消息是它無法找到Spring Security過濾器,從而拒絕解析pring-security.xml文件。

所以從web.xml中刪除您的過濾器,並用這些行添加春季保障,一切應罰款

<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> 

問候,

盧瓦克

+0

試過這個,但得到相同的錯誤。 – karthi

+0

你好,再次閱讀你正面臨的錯誤,它是基本的春天依賴注入相關:錯誤創建名爲'authenticationTokenFilter'的bean ...無法解析匹配構造函數... 你可以分享你的AuthenticationTokenFilter的代碼顯然有一個問題在它的構造函數,這個類是否有一個空的構造函數? – loicmathieu

+0

我用AuthenticationTokenFilter代碼編輯了我的問題。 – karthi