2015-06-22 93 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" /> ,只声明要扫描的软件包以使安全工作,因为它不共享在调度程序配置文件。