Spring Security3简单应用(权限设备在数据库中)   
               添加时间:2013-5-14 点击量: 
 
                1、权限设备在数据库中,典范的五张表。
    1)t_user  用户表
    2)t_role  角色表
    3)t_user_role  用户-角色接洽关系表 
    4)t_resource  资料表
    5)t_role_resource  角色-资料接洽关系表
  2、建表语句
DROP TABLE IF EXISTS `t_resource`;
CREATE TABLE `t_resource` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`name`  varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`url`  varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`name`  varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_role_resource`;
CREATE TABLE `t_role_resource` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`role_id`  int(11) NULL DEFAULT NULL ,
`resource_id`  int(11) NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
CREATE TABLE `t_user` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`account`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`password`  varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`user_id`  int(11) NULL DEFAULT NULL ,
`role_id`  int(11) NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
  3、对应的范畴实体
    1)用户
package cn.luxh.app.domain;
/
  用户
  @author Luxh
 /
public class User {
    
    private Integer id;
    /帐号/
    private String account;
    /暗码/
    private String password;
    
    
    @Override
    public int hashCode() {
        return account.hashCode();
    }
    @Override
    public boolean equals(Object obj) {
        User user = (User) obj;
        return this.account.equals(user.getAccount());
    }
    
    //getter setter
    //... }
    2)角色
package cn.luxh.app.domain;
/
  角色
  @author Luxh
 /
public class Role {
    
    private Integer id;
    /角色名称/
    private String name;
    
    //getter setter
    //...
}
    3)用户-角色
package cn.luxh.app.domain;
/
  用户角色
  @author Luxh
 /
public class UserRole {
    private Integer id;
    /用户id/
    private Integer userId;
    /角色id/
    private Integer roleId;
    
    //getter setter
    //...
}
    4)资料
package cn.luxh.app.domain;
/
  资料
  @author Luxh
 /
public class Resource {
    
    private Integer id;
    /资料名称/
    private String name;
    /接见地址/
    private String url;
    
    //getter setter
}
    5)角色-资料
package cn.luxh.app.domain;
/
  角色资料
  @author Luxh
 /
public class RoleResource {
    private Integer id;
    /角色id/
    private Integer roleId;
    /资料id/
    private Integer resourceId;
    
    //getter setter
}
  4、设备文件
    在web.xml文件中加上如下内容:
<!-- SpringSecurity权限框架 -->  
  <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>  
 <!--  获取Spring Security session的生命周期-->  
    <listener>  
        <listener-class>  
         org.springframework.security.web.session.HttpSessionEventPublisher   
        </listener-class>  
    </listener>  
    当然设备spring器的时辰得把springsecurity的权限设备文件给加载进去:
<!-- 设备Spring器 -->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:application-security.xml</param-value>
    </context-param>
    权限设备文件内容如下:
<?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.2.xsd
                        http://www.springframework.org/schema/security 
                        http://www.springframework.org/schema/security/spring-security-3.1.xsd>
    
    <http pattern=/login security=none />
    <http pattern=/resources/ security=none />
    
    <http auto-config=true use-expressions=true access-denied-page=/denied>
        <!-- default-target-url 指定了从登录页面登录掉队行跳转的页面 always-use-default-target true默示登录成功后强迫跳转 
            authentication-failure-url 默示验证失败掉队入的页面 login-processing-url 设置验证登录验证地址,若是不设置,默认是j_spring_security_check 
            username-parameter,password-parameter 设置登录用户名和暗码的恳求name,默认:j_username,j_password 
            default-target-url=/user/home -->
        <form-login login-page=/login
            always-use-default-target=true
            authentication-failure-url=/login?error=1
            authentication-success-handler-ref=successHandler />
        
        <logout   logout-success-url=/login />
        <!-- error-if-maximum-exceeded 后登岸的账号会挤掉第一次登岸的账号 
            session-fixation-protection 
            防止捏造sessionid进击. 用户登录成功后会烧毁用户当前的session.   
                创建新的session,并把用户信息复制到新session中. -->
        <session-management invalid-session-url=/login?error=3
            session-fixation-protection=none>
            <concurrency-control max-sessions=1
                error-if-maximum-exceeded=true expired-url=/login?error=2 /><!-- 阻拦第二次登录 -->
        </session-management>
        <custom-filter ref=appInterceptor before=FILTER_SECURITY_INTERCEPTOR/>  
    </http>
    <authentication-manager alias=appAuthenticationManager>
        <authentication-provider user-service-ref=userDetailsService>
        </authentication-provider>
    </authentication-manager>
    
    <beans:bean id=appInterceptor class=cn.luxh.app.security.AppSecurityInterceptor>
        <beans:property name=authenticationManager ref=appAuthenticationManager/>
        <beans:property name=accessDecisionManager ref=appAccessDescisionManager/>
        <beans:property name=securityMetadataSource ref=appSecurityMetadataSource/>
    </beans:bean>
    
    
    
    <beans:bean id=userDetailsService class=cn.luxh.app.security.UserDetailsServiceImpl />
    
    <beans:bean id=appSecurityMetadataSource class=cn.luxh.app.security.AppSecurityMetadataSource> 
        <beans:constructor-arg name=roleService ref=roleService></beans:constructor-arg>
        <beans:constructor-arg name=resourceService ref=resourceService></beans:constructor-arg>
    </beans:bean>
    
    <beans:bean id=appAccessDescisionManager class=cn.luxh.app.security.AppAccessDescisionManager/>
    
    <beans:bean id=roleService class=cn.luxh.app.service.RoleServiceImpl/>
    
    <beans:bean id=resourceService class=cn.luxh.app.service.ResourceServiceImpl/>
    
    <!-- 登录成功营业处理惩罚 -->
    <beans:bean id=successHandler
        class=cn.luxh.app.security.LoginAuthenticationSuccessHandler>
        <beans:property name=url value=/index></beans:property> 
    </beans:bean>
</beans:beans>
  5、权限设备文件中的关键类
    1)UserDetailsServiceImpl
package cn.luxh.app.security;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import cn.luxh.app.domain.Role;
import cn.luxh.app.domain.User;
import cn.luxh.app.exception.UserException;
import cn.luxh.app.persistence.RoleMapper;
import cn.luxh.app.persistence.UserMapper;
public class UserDetailsServiceImpl implements UserDetailsService{
    
    private static Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    /
      @param account 登录帐号
     /
    public UserDetails loadUserByUsername(String account)
            throws UsernameNotFoundException {
        log.info(登录账号:+account);
        org.springframework.security.core.userdetails.User userDetails = null;
        try {
            User user = userMapper.ByAccount(account);
            if(user == null) {
                throw new UserException(帐号:+account+ 不存在!);
            }
            Collection<GrantedAuthority> grantedAuthorities = getGrantedAuthorities(user);  
            
            boolean enables = true;  
            boolean accountNonExpired = true;  
            boolean credentialsNonExpired = true;  
            boolean accountNonLocked = true; 
            userDetails = new org.springframework.security.core.userdetails.User(user.getAccount(), user.getPassword(), enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuthorities);  
        }catch(Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return userDetails;
    }
    
    /
      按照用户获取该用户拥有的角色
      @param user
      @return
     /
    private Set<GrantedAuthority> getGrantedAuthorities(User user) {
        Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();  
        List<Role> roles = roleMapper.ByUserId(user.getId()); 
        if(roles != null) {
            for(Role role : roles) {  
                grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
            }  
        }
        return grantedAuthorities;  
    }
}
    2)AppSecurityInterceptor

View Code 
package cn.luxh.app.security;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/
  自定义阻碍器
  @author Luxh
 /
public class AppSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
    
    private static Logger log = LoggerFactory.getLogger(AppSecurityInterceptor.class);
    
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
    
    
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {
        log.info(开端阻碍......);
        FilterInvocation fi = new FilterInvocation(request, response, filterChain);
        InterceptorStatusToken token = super.beforeInvocation(fi);
        try {  
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());  
        } catch (Exception e) {  
            e.printStackTrace();  
        }finally{  
            super.afterInvocation(token,null);  
        }  
    }
    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;
    }
    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return securityMetadataSource;
    }
    
    
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        
    }
    
    @Override
    public void destroy() {
        
    }
    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
        return securityMetadataSource;
    }
    public void setSecurityMetadataSource(
            FilterInvocationSecurityMetadataSource securityMetadataSource) {
        this.securityMetadataSource = securityMetadataSource;
    }
    
    
    
}
    3)AppAccessDescisionManager

View Code 
package cn.luxh.app.security;
import java.util.Collection;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/
  
  接见决定计划器,决意某个用户具有的角色,是否有足够的权限去接见某个资料 ;做终极的接见把握决意 .
  @author Luxh
 
 /
public class AppAccessDescisionManager implements AccessDecisionManager {
    
    private static Logger log = LoggerFactory.getLogger(AppAccessDescisionManager.class);
    
    /
      认证用户是否具有权限接见该url地址 
     /
    @Override
    public void decide(Authentication authentication, Object obj,
            Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
            InsufficientAuthenticationException {
        log.info(AppAccessDescisionManager 验证用户是否具有接见资料的权限);
        
        if(configAttributes != null) {
            Iterator<ConfigAttribute> it = configAttributes.iterator(); 
            while(it.hasNext()) {
                //接见资料须要的权限
                String needRole = it.next().getAttribute();
                 //authentication.getAuthorities()  用户所有的权限  
                for(GrantedAuthority ga:authentication.getAuthorities()){  
                    if(needRole.equals(ga.getAuthority())){  
                        return;  
                    }  
                }  
            }
        }
        
        //没有权限  
        throw new AccessDeniedException(没有权限接见!);  
    }
    
    / 
      启动时辰被AbstractSecurityInterceptor调用,决意AccessDecisionManager是否可以履行传递ConfigAttribute。 
     /  
    @Override
    public boolean supports(ConfigAttribute arg0) {
        return true;
    }
    
    / 
      被安然阻碍器实现调用,包含安然阻碍器将显示的AccessDecisionManager支撑安然对象的类型 
     /  
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
}
    4)AppSecurityMetadataSource

View Code 
package cn.luxh.app.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.AntPathMatcher;
import cn.luxh.app.domain.Resource;
import cn.luxh.app.domain.Role;
import cn.luxh.app.service.ResourceService;
import cn.luxh.app.service.RoleService;
/
  从数据库中查询出资料和权限(角色),并将它们的关系对应起来
  @author Luxh
 
 /
public class AppSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    
    private static Logger log = LoggerFactory.getLogger(AppSecurityMetadataSource.class);
    
    private RoleService roleService;
    
    private ResourceService resourceService;
    
    public RoleService getRoleService() {
        return roleService;
    }
    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }
    public ResourceService getResourceService() {
        return resourceService;
    }
    public void setResourceService(ResourceService resourceService) {
        this.resourceService = resourceService;
    }
    private AntPathMatcher urlMatcher = new AntPathMatcher();
    
    
    / 保存资料和权限的对应关系  key-资料url  value-权限 /  
    private Map<String,Collection<ConfigAttribute>> relationMap = null;
    
    
    public AppSecurityMetadataSource(RoleService roleService,ResourceService resourceService) {
        log.info(履行 AppSecurityMetadataSource 机关办法);
        this.roleService = roleService;
        this.resourceService = resourceService;
        loadResourceAndRoleRelation();
    }
    
    
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
    
    /
      按照恳求的url,获取接见该url所需的权限(角色)
     /
    @Override
    public Collection<ConfigAttribute> getAttributes(Object obj)
            throws IllegalArgumentException {
         //获取恳求的url地址  
        String requestUrl = ((FilterInvocation)obj).getRequestUrl();
        log.info(恳求的 requestUrl :+requestUrl);
        Iterator<String> it = relationMap.keySet().iterator();
        while(it.hasNext()) {
            String url = it.next();
            log.info(设备的 url :+url);
            if(requestUrl.indexOf(?)!=-1) {
                requestUrl = requestUrl.substring(0, url.indexOf(?));
            }
            log.info(hey man :+url);
            if(urlMatcher.match(url, requestUrl)) {
                log.info(已匹配 :+url);
                return relationMap.get(url);
            }
        }
        return null;
    }
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
    
    
    /
      加载资料和角色的对应关系
     /
    private void loadResourceAndRoleRelation() {
        relationMap = new HashMap<String,Collection<ConfigAttribute>>();
        //查出所有角色
        List<Role> roles = roleService.getAll();
        if(roles != null) {
            for(Role role : roles) {
                //查出某个角色可以接见的资料
                List<Resource> resources = resourceService.getByRoleId(role.getId());
                if(resources != null) {
                    for(Resource resource : resources) {
                        Collection<ConfigAttribute> configAttributes = null;  
                        ConfigAttribute configAttribute = new SecurityConfig(role.getName()); 
                        if(relationMap.containsKey(resource.getUrl())){  
                            configAttributes = relationMap.get(resource.getUrl());  
                            configAttributes.add(configAttribute);  
                        }else{  
                            configAttributes = new ArrayList<ConfigAttribute>() ;  
                            configAttributes.add(configAttribute);  
                            relationMap.put(resource.getUrl(), configAttributes);  
                         }  
                    }
                    
                }
                
            }
        }
    }
}
    5)LoginAuthenticationSuccessHandler

View Code 
package cn.luxh.app.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
/
  登录验证成功处理惩罚器
  @author Luxh
 /
public class LoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
    
    private static Logger log = LoggerFactory.getLogger(LoginAuthenticationSuccessHandler.class);
    
    //登录验证成功后须要跳转的url
    private String url;
    
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication) throws IOException,
            ServletException {
        log.info(登录验证成功:+request.getContextPath()+url);
        //response.sendRedirect(request.getContextPath()+url);
        request.getRequestDispatcher(url).forward(request, response);
    }
    
    public void setUrl(String url) {
        this.url = url;
    }
}
  6、此中资料表内容如下
              
  7、源码,含数据库文件和初始化值
        http://files.cnblogs.com/luxh/app4.rar
  8、在页面上的把握权限
    1)引入标签: <%@ taglib prefix=sec uri=http://www.springframework.org/security/tags %>
    2)应用标签:如下,审核操纵时具有ROLE_ADM权限才可以看到。
<sec:authorize ifAnyGranted=ROLE_ADM>
           <li><a href=javascript:auditPage(¥{ctx}/task/auditPage?taskId=¥{task.taskId})>审核</a></li>
</sec:authorize>
  
                     
                  
     
  
 
    
    
1、权限设备在数据库中,典范的五张表。
1)t_user 用户表
2)t_role 角色表
3)t_user_role 用户-角色接洽关系表
4)t_resource 资料表
5)t_role_resource 角色-资料接洽关系表
2、建表语句
DROP TABLE IF EXISTS `t_resource`;
CREATE TABLE `t_resource` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_role_resource`;
CREATE TABLE `t_role_resource` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`role_id` int(11) NULL DEFAULT NULL ,
`resource_id` int(11) NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`account` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`password` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`user_id` int(11) NULL DEFAULT NULL ,
`role_id` int(11) NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
3、对应的范畴实体
1)用户
package cn.luxh.app.domain;
/
用户
@author Luxh
/
public class User {
private Integer id;
/帐号/
private String account;
/暗码/
private String password;
@Override
public int hashCode() {
return account.hashCode();
}
@Override
public boolean equals(Object obj) {
User user = (User) obj;
return this.account.equals(user.getAccount());
}
//getter setter
//... }
2)角色
package cn.luxh.app.domain;
/
角色
@author Luxh
/
public class Role {
private Integer id;
/角色名称/
private String name;
//getter setter
//...
}
3)用户-角色
package cn.luxh.app.domain;
/
用户角色
@author Luxh
/
public class UserRole {
private Integer id;
/用户id/
private Integer userId;
/角色id/
private Integer roleId;
//getter setter
//...
}
4)资料
package cn.luxh.app.domain;
/
资料
@author Luxh
/
public class Resource {
private Integer id;
/资料名称/
private String name;
/接见地址/
private String url;
//getter setter
}
5)角色-资料
package cn.luxh.app.domain;
/
角色资料
@author Luxh
/
public class RoleResource {
private Integer id;
/角色id/
private Integer roleId;
/资料id/
private Integer resourceId;
//getter setter
}
4、设备文件
在web.xml文件中加上如下内容:
<!-- SpringSecurity权限框架 -->
<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>
<!-- 获取Spring Security session的生命周期-->
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
当然设备spring器的时辰得把springsecurity的权限设备文件给加载进去:
<!-- 设备Spring器 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:application-security.xml</param-value>
</context-param>
权限设备文件内容如下:
<?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.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd>
<http pattern=/login security=none />
<http pattern=/resources/ security=none />
<http auto-config=true use-expressions=true access-denied-page=/denied>
<!-- default-target-url 指定了从登录页面登录掉队行跳转的页面 always-use-default-target true默示登录成功后强迫跳转
authentication-failure-url 默示验证失败掉队入的页面 login-processing-url 设置验证登录验证地址,若是不设置,默认是j_spring_security_check
username-parameter,password-parameter 设置登录用户名和暗码的恳求name,默认:j_username,j_password
default-target-url=/user/home -->
<form-login login-page=/login
always-use-default-target=true
authentication-failure-url=/login?error=1
authentication-success-handler-ref=successHandler />
<logout logout-success-url=/login />
<!-- error-if-maximum-exceeded 后登岸的账号会挤掉第一次登岸的账号
session-fixation-protection
防止捏造sessionid进击. 用户登录成功后会烧毁用户当前的session.
创建新的session,并把用户信息复制到新session中. -->
<session-management invalid-session-url=/login?error=3
session-fixation-protection=none>
<concurrency-control max-sessions=1
error-if-maximum-exceeded=true expired-url=/login?error=2 /><!-- 阻拦第二次登录 -->
</session-management>
<custom-filter ref=appInterceptor before=FILTER_SECURITY_INTERCEPTOR/>
</http>
<authentication-manager alias=appAuthenticationManager>
<authentication-provider user-service-ref=userDetailsService>
</authentication-provider>
</authentication-manager>
<beans:bean id=appInterceptor class=cn.luxh.app.security.AppSecurityInterceptor>
<beans:property name=authenticationManager ref=appAuthenticationManager/>
<beans:property name=accessDecisionManager ref=appAccessDescisionManager/>
<beans:property name=securityMetadataSource ref=appSecurityMetadataSource/>
</beans:bean>
<beans:bean id=userDetailsService class=cn.luxh.app.security.UserDetailsServiceImpl />
<beans:bean id=appSecurityMetadataSource class=cn.luxh.app.security.AppSecurityMetadataSource>
<beans:constructor-arg name=roleService ref=roleService></beans:constructor-arg>
<beans:constructor-arg name=resourceService ref=resourceService></beans:constructor-arg>
</beans:bean>
<beans:bean id=appAccessDescisionManager class=cn.luxh.app.security.AppAccessDescisionManager/>
<beans:bean id=roleService class=cn.luxh.app.service.RoleServiceImpl/>
<beans:bean id=resourceService class=cn.luxh.app.service.ResourceServiceImpl/>
<!-- 登录成功营业处理惩罚 -->
<beans:bean id=successHandler
class=cn.luxh.app.security.LoginAuthenticationSuccessHandler>
<beans:property name=url value=/index></beans:property>
</beans:bean>
</beans:beans>
5、权限设备文件中的关键类
1)UserDetailsServiceImpl
package cn.luxh.app.security;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import cn.luxh.app.domain.Role;
import cn.luxh.app.domain.User;
import cn.luxh.app.exception.UserException;
import cn.luxh.app.persistence.RoleMapper;
import cn.luxh.app.persistence.UserMapper;
public class UserDetailsServiceImpl implements UserDetailsService{
private static Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private UserMapper userMapper;
@Autowired
private RoleMapper roleMapper;
/
@param account 登录帐号
/
public UserDetails loadUserByUsername(String account)
throws UsernameNotFoundException {
log.info(登录账号:+account);
org.springframework.security.core.userdetails.User userDetails = null;
try {
User user = userMapper.ByAccount(account);
if(user == null) {
throw new UserException(帐号:+account+ 不存在!);
}
Collection<GrantedAuthority> grantedAuthorities = getGrantedAuthorities(user);
boolean enables = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
userDetails = new org.springframework.security.core.userdetails.User(user.getAccount(), user.getPassword(), enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuthorities);
}catch(Exception e) {
log.error(e.getMessage());
e.printStackTrace();
}
return userDetails;
}
/
按照用户获取该用户拥有的角色
@param user
@return
/
private Set<GrantedAuthority> getGrantedAuthorities(User user) {
Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
List<Role> roles = roleMapper.ByUserId(user.getId());
if(roles != null) {
for(Role role : roles) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
}
return grantedAuthorities;
}
}
2)AppSecurityInterceptor

View Code 
package cn.luxh.app.security;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/
自定义阻碍器
@author Luxh
/
public class AppSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
private static Logger log = LoggerFactory.getLogger(AppSecurityInterceptor.class);
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
log.info(开端阻碍......);
FilterInvocation fi = new FilterInvocation(request, response, filterChain);
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} catch (Exception e) {
e.printStackTrace();
}finally{
super.afterInvocation(token,null);
}
}
@Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return securityMetadataSource;
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void destroy() {
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
}
public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}
}
3)AppAccessDescisionManager

View Code 
package cn.luxh.app.security;
import java.util.Collection;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/
接见决定计划器,决意某个用户具有的角色,是否有足够的权限去接见某个资料 ;做终极的接见把握决意 .
@author Luxh
/
public class AppAccessDescisionManager implements AccessDecisionManager {
private static Logger log = LoggerFactory.getLogger(AppAccessDescisionManager.class);
/
认证用户是否具有权限接见该url地址
/
@Override
public void decide(Authentication authentication, Object obj,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
InsufficientAuthenticationException {
log.info(AppAccessDescisionManager 验证用户是否具有接见资料的权限);
if(configAttributes != null) {
Iterator<ConfigAttribute> it = configAttributes.iterator();
while(it.hasNext()) {
//接见资料须要的权限
String needRole = it.next().getAttribute();
//authentication.getAuthorities() 用户所有的权限
for(GrantedAuthority ga:authentication.getAuthorities()){
if(needRole.equals(ga.getAuthority())){
return;
}
}
}
}
//没有权限
throw new AccessDeniedException(没有权限接见!);
}
/
启动时辰被AbstractSecurityInterceptor调用,决意AccessDecisionManager是否可以履行传递ConfigAttribute。
/
@Override
public boolean supports(ConfigAttribute arg0) {
return true;
}
/
被安然阻碍器实现调用,包含安然阻碍器将显示的AccessDecisionManager支撑安然对象的类型
/
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
4)AppSecurityMetadataSource

View Code 
package cn.luxh.app.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.AntPathMatcher;
import cn.luxh.app.domain.Resource;
import cn.luxh.app.domain.Role;
import cn.luxh.app.service.ResourceService;
import cn.luxh.app.service.RoleService;
/
从数据库中查询出资料和权限(角色),并将它们的关系对应起来
@author Luxh
/
public class AppSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private static Logger log = LoggerFactory.getLogger(AppSecurityMetadataSource.class);
private RoleService roleService;
private ResourceService resourceService;
public RoleService getRoleService() {
return roleService;
}
public void setRoleService(RoleService roleService) {
this.roleService = roleService;
}
public ResourceService getResourceService() {
return resourceService;
}
public void setResourceService(ResourceService resourceService) {
this.resourceService = resourceService;
}
private AntPathMatcher urlMatcher = new AntPathMatcher();
/ 保存资料和权限的对应关系 key-资料url value-权限 /
private Map<String,Collection<ConfigAttribute>> relationMap = null;
public AppSecurityMetadataSource(RoleService roleService,ResourceService resourceService) {
log.info(履行 AppSecurityMetadataSource 机关办法);
this.roleService = roleService;
this.resourceService = resourceService;
loadResourceAndRoleRelation();
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
/
按照恳求的url,获取接见该url所需的权限(角色)
/
@Override
public Collection<ConfigAttribute> getAttributes(Object obj)
throws IllegalArgumentException {
//获取恳求的url地址
String requestUrl = ((FilterInvocation)obj).getRequestUrl();
log.info(恳求的 requestUrl :+requestUrl);
Iterator<String> it = relationMap.keySet().iterator();
while(it.hasNext()) {
String url = it.next();
log.info(设备的 url :+url);
if(requestUrl.indexOf(?)!=-1) {
requestUrl = requestUrl.substring(0, url.indexOf(?));
}
log.info(hey man :+url);
if(urlMatcher.match(url, requestUrl)) {
log.info(已匹配 :+url);
return relationMap.get(url);
}
}
return null;
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
/
加载资料和角色的对应关系
/
private void loadResourceAndRoleRelation() {
relationMap = new HashMap<String,Collection<ConfigAttribute>>();
//查出所有角色
List<Role> roles = roleService.getAll();
if(roles != null) {
for(Role role : roles) {
//查出某个角色可以接见的资料
List<Resource> resources = resourceService.getByRoleId(role.getId());
if(resources != null) {
for(Resource resource : resources) {
Collection<ConfigAttribute> configAttributes = null;
ConfigAttribute configAttribute = new SecurityConfig(role.getName());
if(relationMap.containsKey(resource.getUrl())){
configAttributes = relationMap.get(resource.getUrl());
configAttributes.add(configAttribute);
}else{
configAttributes = new ArrayList<ConfigAttribute>() ;
configAttributes.add(configAttribute);
relationMap.put(resource.getUrl(), configAttributes);
}
}
}
}
}
}
}
5)LoginAuthenticationSuccessHandler

View Code 
package cn.luxh.app.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
/
登录验证成功处理惩罚器
@author Luxh
/
public class LoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
private static Logger log = LoggerFactory.getLogger(LoginAuthenticationSuccessHandler.class);
//登录验证成功后须要跳转的url
private String url;
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException,
ServletException {
log.info(登录验证成功:+request.getContextPath()+url);
//response.sendRedirect(request.getContextPath()+url);
request.getRequestDispatcher(url).forward(request, response);
}
public void setUrl(String url) {
this.url = url;
}
}
6、此中资料表内容如下
              
7、源码,含数据库文件和初始化值
http://files.cnblogs.com/luxh/app4.rar
8、在页面上的把握权限
1)引入标签: <%@ taglib prefix=sec uri=http://www.springframework.org/security/tags %>
2)应用标签:如下,审核操纵时具有ROLE_ADM权限才可以看到。
<sec:authorize ifAnyGranted=ROLE_ADM>
<li><a href=javascript:auditPage(¥{ctx}/task/auditPage?taskId=¥{task.taskId})>审核</a></li>
</sec:authorize>





