[英]Spring security configuration error for admin request
我正在尝试将我的Spring应用程序配置为具有带有Spring安全性的相当基本的安全性系统。 我希望没有安全过滤器即可提供资源,要过滤标准页面以检查用户是否具有角色“ User”,而要提供/ admin /页面以检查角色是否为“ Admin”。
我所拥有的是:
springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在web.xml中,而spring-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
,现在越来越清楚了。 这个问题在我SpringSecurityServiceImpl
的Autowired
utenteDao实例为null。 我像这样编辑spring-security.xml文件,希望Spring能够理解@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;
}
}
Spring安全性登录和注销表单期望CSRF令牌在发布请求中发送。 您可以使用隐藏变量添加令牌:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
在Spring Security登录表单中添加以上行。 和退出也需要一个post
请求方法。 对服务器的每个发布请求都将检查这些令牌,您可以将其设置为请求标头。 如果您不想这样做,请禁用csrf令牌安全性。 您可以使用安全配置的http部分中的csrf
标记禁用它。 csrf
具有禁用它的属性。
<http>
<csrf />
</http>
阅读本文以了解更多信息。
编辑:
您已经在安全认证标签中提到了user-service-ref="SpringSecurityServiceImpl"
,但是Service
类没有标识符。 给您的服务类别一个标识符,最好使用驼峰字符。
@Service("springSecurityServiceImpl") // talking about this identifier
@Transactional
public class SpringSecurityServiceImpl implements UserDetailsService {}
身份验证提供程序bean应该是:
<security:authentication-manager>
<security:authentication-provider user-service-ref="springSecurityServiceImpl">
<security:password-encoder hash="bcrypt" />
</security:authentication-provider>
</security:authentication-manager>
还要检查您的DAO类是否标记为@Repository
组件,以使自动装配完美工作。
我解决了问题。 到处搜索,我发现安全性和servlet具有不同的上下文,因此基本上我必须添加<context:component-scan base-package="org.fabrizio.fantacalcio.utility, org.fabrizio.fantacalcio.model.dao" />
也在security-config.xml
文件中,仅声明要扫描以使安全性起作用的包,因为它不共享在分派器配置文件中声明的bean。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.