spring-security有两种方法显示比较简单的配置userDetailService
1、 简单实现用户名和密码、权限的验证(使用默认的过滤器)
spring-securit使用authenticationManager来校验用户名和密码,authenticationManager是依靠其包含一系列authenticationProvider完成验证的, 如果配置只没有指明authenticationProvider默认DoAuthenticationProvider,只要指明其UserService就可以。如下图:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
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.0.xsd">
<http auto-config="true">
<intercept-url pattern="/login.jsp" filters="none"/>
<form-login login-page="/login.jsp"
login-processing-url="/j_security_check"
authentication-success-handler-ref="loginHandler"
authentication-failure-handler-ref="loginHandler"/>
<logout success-handler-ref="loginHandler"/>
<intercept-url pattern="/admin/**" access="ROLE_ADMIN,ROLE_USER"/>
</http>
<authentication-manager">
<authentication-provider user-service-ref="userService"/>
</authentication-manager>
</beans:beans>
其中userService要实现UserDetailsService接口,其中的关键方法是 UserDetails loadUserByUsername( String username ).
这个方法返回一个UserDetails的接口,我们需要我们的User类实现UserDetails接口,其中的关键方法是 Collection<GrantedAuthority> getAuthorities(), 这个方法返回一个GrantedAuthority接口的集合。
UserDetails接口可以返回用户名,密码,权限的集合Collection<GrantedAuthority>,是否停用等信息。
我们可以让Role实现这个接口,其中关键方法是 String getAuthority(),即返回权限字符串,如ROLE_ADMIN。
UserService主要内容
@Repository("userService")
public class UserService implements UserDetailsService{
@Autowired
private HibernateTemplate hibernateTemplate;
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
List<User> list = hibernateTemplate.find("from User where username=?",username);
if(list == null || list.size()==0)
throw new UsernameNotFoundException("用户" + username + " 不存在!!!");
User user = list.get(0);
return user;
}
}
2、在spring-security.xml中配置验证自定义的过滤器(在1步骤的基础上)
spring-security中需要配置验证过滤器来实现整个拦截的过程,其中需要配置一下三个来实现。
authenticationManager:第一步已经完成配过。判断用户名和密码是否相等。
securityMetadataSource:根据url得到需要的角色名称FilterInvocationSecurityMetadataSource.getAttributes()方法实现,需要初始化所有url对应的角色(可以放到初始化函数或者构造函数)
accessDecisionManager:将根据上面得到url需要的角色与用户角色对比,有相等则通过,AccessDecisionManager.decide()方法实现。
security.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
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.0.xsd">
<http auto-config="true">
<intercept-url pattern="/login.jsp" filters="none"/>
<form-login login-page="/login.jsp"
login-processing-url="/j_security_check"
authentication-success-handler-ref="loginHandler"
authentication-failure-handler-ref="loginHandler"/>
<logout success-handler-ref="loginHandler"/>
<intercept-url pattern="/admin/**" access="ROLE_ADMIN,ROLE_USER"/>
<custom-filter ref="myFilterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
</http>
<beans:bean id="myFilterSecurityInterceptor" class="com.wxg.general.MyFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>
<authentication-manager alias="myAuthenticationManager">
<authentication-provider user-service-ref="userDao">
</authentication-provider>
</authentication-manager>
</beans:beans>
MyFilterSecurityInterceptor.java的主要方法
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
FilterInvocation fileInvocation = new FilterInvocation(request, response, chain);
//验证权限在beforeInvocation方法中
InterceptorStatusToken interceptorStatusToken = this.beforeInvocation(fileInvocation);
System.out.println("FilterSecurityInterceptor -method-doFiler");
fileInvocation.getChain().doFilter(request, response);
this.afterInvocation(interceptorStatusToken, null);
}
MySecurityMetadataSource 主要内容
@Controller("mySecurityMetadataSource")
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private Map<String, List<ConfigAttribute>> mp;
private UrlMatcher urlMatcher;
public MySecurityMetadataSource()
{
//构造函数初始化,必须把所有菜单配上权限放入mp
super();
this.mp = new HashMap<String, List<ConfigAttribute>>();
this.urlMatcher = new AntUrlPathMatcher();
List<ConfigAttribute> list = new ArrayList<ConfigAttribute>();
ConfigAttribute cb = new SecurityConfig("ROLE_ADMIN"); // 构造一个权限(角色)
ConfigAttribute cbUser = new SecurityConfig("ROLE_USER"); // 构造一个权限(角色)
list.add(cb);
list.add(cbUser);
mp.put("/admin/adminMenu.jsp", list);
}
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
String requestUrl = ((FilterInvocation) object).getRequestUrl();
Iterator<String> iter = this.mp.keySet().iterator();
while (iter.hasNext()) {
String temp = iter.next();
if (this.urlMatcher.pathMatchesUrl(requestUrl, temp)) {
return mp.get(temp);
}
}
return null;
}
}
MyAccessDecisionManager 类主要内容
@Service( "myAccessDecisionManager" )
public class MyAccessDecisionManager implements AccessDecisionManager {
public void decide( Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes )
throws AccessDeniedException, InsufficientAuthenticationException {
//负责校验请求的url需要的权限,和登录权限是否有相等。
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while ( ite.hasNext() ) {
ConfigAttribute ca = ite.next();
String needRole = ( (SecurityConfig) ca ).getAttribute();
for ( GrantedAuthority ga : authentication.getAuthorities() ) {
if ( ga.getAuthority().equals( "ROLE_ADMIN" ) || needRole.equals( ga.getAuthority() ) ) {
return;
}
}
}
throw new AccessDeniedException( "没有权限" );
}
}