2015-06-22 94 views
2

我想配置我的Spring應用程序有一個非常基本的安全系統與Spring安全。 我想要沒有安全過濾器的服務資源,要過濾的標準頁面檢查用戶是否具有「用戶」角色和/ admin /頁面來檢查角色是否爲「Admin」。管理請求彈簧安全配置錯誤

我所擁有的是:

springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy

<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
在web.xml

,而彈簧security.xml文件是:

<security:http security="none" pattern="/resources/**"/> 
<security:http auto-config="true" use-expressions="true" > 
    <security:intercept-url pattern="/admin/**" access="hasRole('Admin')" /> 
    <security:logout logout-success-url="/welcome" logout-url="/logout" /> 
    <security:form-login login-page="/FormLogin" 
     default-target-url="/welcome" 
     username-parameter="username" 
     password-parameter="hashPwd" 
     authentication-failure-url="/login?error" 
     /> 
</security:http> 

<security:authentication-manager> 
    <security:authentication-provider user-service-ref="controlloUtente"> 
    <security:password-encoder hash="bcrypt" /> 
    </security:authentication-provider> 
</security:authentication-manager> 


<beans:bean id="controlloUtente" 
    class="org.fabrizio.fantacalcio.utility.SpringSecurityServiceImpl"> 
</beans:bean> 

然後我配置了這個類:

package org.fabrizio.fantacalcio.utility; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 

import org.fabrizio.fantacalcio.model.beans.Utente; 
import org.fabrizio.fantacalcio.model.dao.UtenteDaoImpl; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.User; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 

@Service 
@Transactional 
public class SpringSecurityServiceImpl implements UserDetailsService{ 

    @Autowired 
    private UtenteDaoImpl utenteDao; 

    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     Utente utente = utenteDao.getUtenteByUsername(username); 
     if(utente == null){ 
      throw new UsernameNotFoundException("L'utente inserito non è stato trovato"); 
     } 
     return convertUtente(utente); 
    } 

    private UserDetails convertUtente(Utente utente) { 
     UserDetails ud = new User(utente.getUsername(), utente.getHashPwd(), true, true, true, true, getRoles(utente)); 
     return ud; 
    } 

    private Collection<? extends GrantedAuthority> getRoles(Utente utente) { 
     GrantedAuthority auth = new SimpleGrantedAuthority(utente.getRuolo().getNome()); 
     List<GrantedAuthority> listaAuth = new ArrayList<GrantedAuthority>(); 
     listaAuth.add(auth); 
     return listaAuth; 
    } 

} 

及以下之一:

package org.fabrizio.fantacalcio.utility; 

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import org.springframework.core.PriorityOrdered; 
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; 
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; 
import org.springframework.stereotype.Component; 

@Component 
public class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered { 

    @Override 
    public Object postProcessAfterInitialization(Object bean, String beanName) 
      throws BeansException { 
     if(bean instanceof Jsr250MethodSecurityMetadataSource) { 
      ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(""); 
     } 
     if(bean instanceof DefaultMethodSecurityExpressionHandler) { 
      ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(""); 
     } 
//  if(bean instanceof DefaultWebSecurityExpressionHandler) { 
//   ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(""); 
//  } 
     return bean; 
    } 

    @Override 
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
      throws BeansException { 
     return bean; 
    } 

    @Override 
    public int getOrder() { 
     return PriorityOrdered.HIGHEST_PRECEDENCE; 
    } 
} 

但沒有任何工程。 我的formLogin不使用彈簧形式,而是一個經典的形式。

當我登錄,我試圖讓像/admin/testpage一個PGE,我重定向到FormLogin頁,即使我有管理員的角色,這就是調試輸出:

22/06/2015 10:03:04 - DEBUG - (AntPathRequestMatcher.java:141) - Request '/admin/formregistrazione' matched by universal pattern '/**' 
22/06/2015 10:03:04 - DEBUG - (HttpSessionRequestCache.java:43) - DefaultSavedRequest added to Session: DefaultSavedRequest[http://localhost:8080/Fantacalcio/admin/FormRegistrazione] 
22/06/2015 10:03:04 - DEBUG - (ExceptionTranslationFilter.java:202) - Calling Authentication entry point. 
22/06/2015 10:03:04 - DEBUG - (DefaultRedirectStrategy.java:39) - Redirecting to 'http://localhost:8080/Fantacalcio/FormLogin' 
22/06/2015 10:03:04 - DEBUG - (HttpSessionSecurityContextRepository.java:337) - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. 

有時候,登錄後,我收到此消息:

HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'. 

我做錯了什麼?我總是必須使用令牌?爲什麼流程永遠不會進入SpringSecurityServiceImpl類?

感謝

編輯:我禁用csrf,它現在是越來越清楚了。問題出在我的SpringSecurityServiceImplAutowired utenteDao實例爲空。我編輯的彈簧security.xml文件這樣,希望春天理解@Service註解類,但它不工作:

<security:authentication-manager> 
     <security:authentication-provider user-service-ref="SpringSecurityServiceImpl"> 
     <security:password-encoder hash="bcrypt" /> 
     </security:authentication-provider> 
    </security:authentication-manager> 

我UtenteDao類

package org.fabrizio.fantacalcio.model.dao; 

import java.util.List; 

import org.fabrizio.fantacalcio.model.beans.Utente; 
import org.hibernate.criterion.Restrictions; 
import org.springframework.stereotype.Repository; 

@Repository 
public class UtenteDaoImpl extends BaseDaoImpl<Utente> implements UtenteDao{ 

    public UtenteDaoImpl() { 
    System.out.println("test"); 
    } 

    @SuppressWarnings("unchecked") 
    public List<Utente> trovaUtentiAttivi(){ 
     return getSession().createCriteria(Utente.class).add(Restrictions.eq("attivo", true)).list(); 
    } 


    @SuppressWarnings("unchecked") 
    public Utente getUtenteFromCredenziali(Utente utente){ 
     List<Utente> utenteTrovato = getSession().createCriteria(Utente.class) 
       .add(Restrictions.eq("username", utente.getUsername())) 
       .add(Restrictions.eq("hashPwd", utente.getHashPwd())) 
       .list(); 
     Utente utenteLoggato = utenteTrovato.size() == 0 ? null : utenteTrovato.get(0); 
     return utenteLoggato; 
    } 

    public Boolean usernameExists(String username){ 
     return getSession().createCriteria(Utente.class) 
       .add(Restrictions.eq("username", username)) 
       .list().size() > 0; 
    } 

    @SuppressWarnings("unchecked") 
    public Utente getUtenteByUsername(String username){ 
     List<Utente> utenteTrovato = getSession().createCriteria(Utente.class) 
       .add(Restrictions.eq("username", username)) 
       .list(); 
     Utente utenteLoggato = utenteTrovato.size() == 0 ? null : utenteTrovato.get(0); 
     return utenteLoggato; 
    } 
} 
+0

爲什麼不能在securityApplicationContext.xml中看到任何CSRF配置? –

+0

我問,我是否應該使用csrf標記? – lateralus

+0

實際上沒有,我也看不到你在哪裏配置CSRF,所以你不應該得到那個錯誤。但是因爲你有這個錯誤,你已經啓用了CSRF事件,儘管它默認啓用了。 –

回答

0

春季安全登錄和註銷形式的期望CSRF令牌將在發佈請求中發送。您可以使用隱藏變量添加令牌:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 

在春季安全登錄表單中添加上面的行。並且註銷也需要是一個post請求方法。每個向服務器發送的請求都會檢查這些令牌,您可以將其設置爲請求頭。如果您不想執行此操作並禁用csrf令牌安全性。 您可以在安全配置的http部分使用csrf標記禁用它。 csrf有屬性將其禁用。

<http> 
    <csrf /> 
</http> 

閱讀this article瞭解更多。

編輯:

您已經在安全認證標籤提到user-service-ref="SpringSecurityServiceImpl"Service類沒有標識。給你的服務類一個標識符,更喜歡駱駝大小寫字符。

@Service("springSecurityServiceImpl") // talking about this identifier 
@Transactional 
public class SpringSecurityServiceImpl implements UserDetailsService {} 

和認證提供豆應該是:

<security:authentication-manager> 
    <security:authentication-provider user-service-ref="springSecurityServiceImpl"> 
    <security:password-encoder hash="bcrypt" /> 
    </security:authentication-provider> 
</security:authentication-manager> 

而且還要檢查,如果你的DAO類被標記爲@Repository組件的自動裝配完美運行。

+0

添加到xml配置文件不會禁用csrf保護,並且我無法找到通過xml執行此操作的方法。 – lateralus

+1

你究竟添加了什麼?你可以把它粘貼在這裏嗎?它應該像。 –

+0

我禁用了它,但我遇到了一些新問題,我編輯了這個問題。 – lateralus

0

我解決了這個問題。 搜索我發現安全和servlet具有不同的上下文,所以基本上我必須在security-config.xml文件上也添加<context:component-scan base-package="org.fabrizio.fantacalcio.utility, org.fabrizio.fantacalcio.model.dao" /> ,只聲明要掃描的軟件包以使安全工作,因爲它不共享在調度程序配置文件。