您的位置:首页 > 编程语言 > Java开发

[转]spring security 3 中使用自定义数据库来设置权限

2012-11-21 17:51 302 查看
转http://blog.csdn.net/remote_roamer/article/details/5713777

在spring security3中使用自己定义的数据结构来实现权限设置。

1.数据库

◦用户表

◦角色表

◦action表,即资源表

◦角色-用户关联表

◦actiion-角色关联表

2.配置过程

◦web.xml中加入过滤器


<!-- 配置spiring security -->
<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>
<!-- 配置spiring security结束 -->

◦在applicationContext.xml中import spring security部分的配置

<import resource="security3.0_JPA.xml"/> 

◦配置import resource="security3.0_JPA.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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" access-denied-page="/jsp/accessDenied.jsp">
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,
这个filter位于FILTER_SECURITY_INTERCEPTOR之前 -->
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />
</http>
<!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,
我们的所有控制将在这三个类中实现,解释详见具体配置 -->
<beans:bean id="myFilter" class="com.softvan.spring.security.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="MyAuthenticationManager" />
<!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
<beans:property name="accessDecisionManager" ref="AccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="MySecurityMetadataSource" />
</beans:bean>
<!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 -->
<beans:bean id="MySecurityMetadataSource" init-method="loadResourceDefine" class="com.softvan.spring.security.InvocationSecurityMetadataSourceService">
<beans:property name="roleService" ref="RoleService" />
<beans:property name="actionService" ref="ActionService" />
</beans:bean>

<!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
<authentication-manager alias="MyAuthenticationManager">
<authentication-provider user-service-ref="UserDetailService">
<!--
<s:password-encoder hash="sha" />
-->
</authentication-provider>
</authentication-manager>
</beans:beans> 

3.相关java代码

◦AccessDecisionManager.java

/**
*
*/
package com.softvan.spring.security;
import org.apache.log4j.Logger;
/**
* @author 徐泽宇(roamer)
*
* 2010-7-4
*/
import java.util.Collection;
import java.util.Iterator;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
@Service("AccessDecisionManager")
public class AccessDecisionManager implements org.springframework.security.access.AccessDecisionManager {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(AccessDecisionManager.class);
// In this method, need to compare authentication with configAttributes.
// 1, A object is a URL, a filter was find permission configuration by this
// URL, and pass to here.
// 2, Check authentication has attribute in permission configuration
// (configAttributes)
// 3, If not match corresponding authentication, throw a
// AccessDeniedException.
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if (logger.isDebugEnabled()) {
logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - start"); //$NON-NLS-1$
}
if (configAttributes == null) {
if (logger.isDebugEnabled()) {
logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - end"); //$NON-NLS-1$
}
return;
}
if (logger.isDebugEnabled()){
logger.debug("正在访问的url是:"+object.toString());
}
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
logger.debug("needRole is:"+ca.getAttribute());
String needRole = ((SecurityConfig) ca).getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
logger.debug("/t授权信息是:"+ga.getAuthority());
if (needRole.equals(ga.getAuthority())) { // ga is user's role.
if (logger.isDebugEnabled()) {
logger.debug("判断到,needRole 是"+needRole+",用户的角色是:"+ga.getAuthority()+",授权数据相匹配");
logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - end"); //$NON-NLS-1$
}
return;
}
}
}
throw new AccessDeniedException("没有权限");
}
public boolean supports(ConfigAttribute attribute) {
// TODO Auto-generated method stub
return true;
}
public boolean supports(Class<?> clazz) {
return true;
}


◦FilterSecurityInterceptor.java


/**
*
*/
package com.softvan.spring.security;
import org.apache.log4j.Logger;
/**
* @author 徐泽宇(roamer)
*
* 2010-7-4
*/
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(FilterSecurityInterceptor.class);
private FilterInvocationSecurityMetadataSource securityMetadataSource;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("doFilter(ServletRequest, ServletResponse, FilterChain) - start"); //$NON-NLS-1$
}
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
if (logger.isDebugEnabled()) {
logger.debug("doFilter(ServletRequest, ServletResponse, FilterChain) - end"); //$NON-NLS-1$
}
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return this.securityMetadataSource;
}
public Class<? extends Object> getSecureObjectClass() {
return FilterInvocation.class;
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}
public void destroy() {
// TODO Auto-generated method stub
}
public void init(FilterConfig filterconfig) throws ServletException {
// TODO Auto-generated method stub
}


◦InvocationSecurityMetadataSourceService.java


/**
*
*/
package com.softvan.spring.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
import org.springframework.stereotype.Service;
import com.alcor.acl.domain.TAction;
import com.alcor.acl.domain.TRole;
import com.alcor.acl.service.ActionService;
import com.alcor.acl.service.RoleService;
/*
*
* 最核心的地方,就是提供某个资源对应的权限定义,即getAttributes方法返回的结果。
* 注意,我例子中使用的是AntUrlPathMatcher这个path matcher来检查URL是否与资源定义匹配,
* 事实上你还要用正则的方式来匹配,或者自己实现一个matcher。
*
* 此类在初始化时,应该取到所有资源及其对应角色的定义
*
* 说明:对于方法的spring注入,只能在方法和成员变量里注入,
* 如果一个类要进行实例化的时候,不能注入对象和操作对象,
* 所以在构造函数里不能进行操作注入的数据。
*/
@Service("InvocationSecurityMetadataSourceService")
public class InvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(InvocationSecurityMetadataSourceService.class);

private RoleService roleService ;
private ActionService actionService;

private UrlMatcher urlMatcher = new AntUrlPathMatcher();
private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
public void loadResourceDefine()throws Exception {
this.resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

//通过数据库中的信息设置,resouce和role
for (TRole item:this.roleService.getAllRoles()){
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
ConfigAttribute ca = new SecurityConfig(item.getRoleName());
atts.add(ca);
List<TAction> tActionList = actionService.findByRoleID(item.getRoleId());
//把资源放入到spring security的resouceMap中
for(TAction tAction:tActionList){
logger.debug("获得角色:["+item.getRoleName()+"]拥有的acton有:"+tAction.getActionUrl());
this.resourceMap.put(tAction.getActionUrl(), atts);
}
}

/*//通过硬编码设置,resouce和role
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
ConfigAttribute ca = new SecurityConfig("admin");
atts.add(ca);
resourceMap.put("/jsp/admin.jsp", atts);
resourceMap.put("/swf/zara.html", atts);*/

}
// According to a URL, Find out permission configuration of this URL.
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
if (logger.isDebugEnabled()) {
logger.debug("getAttributes(Object) - start"); //$NON-NLS-1$
}
// guess object is a URL.
String url = ((FilterInvocation) object).getRequestUrl();
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
if (urlMatcher.pathMatchesUrl(url, resURL)) {
Collection<ConfigAttribute> returnCollection = resourceMap.get(resURL);
if (logger.isDebugEnabled()) {
logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$
}
return returnCollection;
}
}
if (logger.isDebugEnabled()) {
logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$
}
return null;
}
public boolean supports(Class<?> clazz) {
return true;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
public RoleService getRoleService() {
return roleService;
}
public void setRoleService(RoleService roleService) {
this.roleService = roleService;
}
public ActionService getActionService() {
return actionService;
}
public void setActionService(ActionService actionService) {
this.actionService = actionService;
}


◦UserDetailService.java

/**
*
*/
package com.softvan.spring.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
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 com.alcor.acl.domain.TRole;
import com.alcor.acl.domain.TUser;
@Service("UserDetailService")
public class UserDetailService implements UserDetailsService {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(UserDetailService.class);
@Inject
com.alcor.acl.component.User user ;

public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("loadUserByUsername(String) - start"); //$NON-NLS-1$
}

Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>();

String password=null;
//取得用户的密码
TUser tUser = user.getUserByName(username);
if (tUser ==null){
String message = "用户"+username+"不存在";
logger.error(message);
throw new UsernameNotFoundException(message);
}
password=user.getUserByName(username).getPassword();

//获得用户的角色
Set<TRole> tRoles =tUser.getTRoles();
for(TRole item : tRoles){
GrantedAuthorityImpl grantedAuthorityImpl = new GrantedAuthorityImpl(item.getRoleName());
if (logger.isDebugEnabled()){
logger.debug("用户:["+tUser.getName()+"]拥有角色:["+item.getRoleName()+"],即spring security中的access");
}
auths.add(grantedAuthorityImpl);
}

User user = new User(username,password, true, true, true, true, auths);

if (logger.isDebugEnabled()) {
logger.debug("loadUserByUsername(String) - end"); //$NON-NLS-1$
}
return user;
}
}












阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: