2011-04-28

这几天学习了一下Spring Security3.1,从官网下载了Spring Security3.1版本进行练习,经过多次尝试才摸清了其中的一些原理。本人不才,希望能帮助大家。还有,这次我第二次写博客啊,文体不是很行。希望能让观看者不产生疲惫的感觉,我已经心满意足了。
一、数据库结构
     先来看一下数据库结构,采用的是基于角色-资源-用户的权限管理设计。(MySql数据库)
    为了节省篇章,只对比较重要的字段进行注释。
    1.用户表Users
    CREATE TABLE `users` (
       -- 账号是否有限 1. 是 0.否
       `enable` int(11) default NULL,
       `password` varchar(255) default NULL,
       `account` varchar(255) default NULL,
       `id` int(11) NOT NULL auto_increment,
       PRIMARY KEY  (`id`)
    )
 
   2.角色表Roles
   CREATE TABLE `roles` (
     `enable` int(11) default NULL,
     `name` varchar(255) default NULL,
     `id` int(11) NOT NULL auto_increment,
     PRIMARY KEY  (`id`)
   )
 
   3 用户_角色表users_roles
   CREATE TABLE `users_roles` (
     --用户表的外键
     `uid` int(11) default NULL,
     --角色表的外键
     `rid` int(11) default NULL,
     `urId` int(11) NOT NULL auto_increment,
     PRIMARY KEY  (`urId`),
     KEY `rid` (`rid`),
     KEY `uid` (`uid`),
    CONSTRAINT `users_roles_ibfk_1` FOREIGN KEY (`rid`) REFERENCES `roles` (`id`),
    CONSTRAINT `users_roles_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `users` (`id`)
   )
 
   4.资源表resources
   CREATE TABLE `resources` (
     `memo` varchar(255) default NULL,
     -- 权限所对应的url地址
     `url` varchar(255) default NULL,
     --优先权
     `priority` int(11) default NULL,
     --类型
     `type` int(11) default NULL,
     --权限所对应的编码,例201代表发表文章
     `name` varchar(255) default NULL,
     `id` int(11) NOT NULL auto_increment,
     PRIMARY KEY  (`id`)
   ) 
 
   5.角色_资源表roles_resources
    CREATE TABLE `roles_resources` (
      `rsid` int(11) default NULL,
      `rid` int(11) default NULL,
      `rrId` int(11) NOT NULL auto_increment,
      PRIMARY KEY  (`rrId`),
      KEY `rid` (`rid`),
      KEY `roles_resources_ibfk_2` (`rsid`),
      CONSTRAINT `roles_resources_ibfk_2` FOREIGN KEY (`rsid`) REFERENCES `resources` (`id`),
      CONSTRAINT `roles_resources_ibfk_1` FOREIGN KEY (`rid`) REFERENCES `roles` (`id`)
      )
 
  二、系统配置
   所需要的jar包,请自行到官网下载,我用的是Spring Security3.1.0.RC1版的。把dist下的除了源码件包导入就行了。还有那些零零碎的   数据库驱动啊,log4j.jar等等,我相信在用Spring Security之前,大家已经会的了。
  1) web.xml
  
[xhtml] view plaincopyprint?
<!-- Spring -->  
   <context-param>  
     <param-name>contextConfigLocation</param-name>  
     <param-value>classpath:applicationContext.xml,classpath:applicationContext-security.xml</param-value>  
   </context-param>  
     
       
   <listener>  
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
   </listener>  
   <!-- 权限 -->  
   <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 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml,classpath:applicationContext-security.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 权限 --> <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> 
 这里主要是配置了让容器启动的时候加载application-security.xml和Spring Security的权限过滤器代理,让其过滤所有的客服请求。
 2)application-security.xml
  
[xhtml] view plaincopyprint?
<?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.1.xsd">  
                           
     <global-method-security pre-post-annotations="enabled" />   
     <!-- 该路径下的资源不用过滤 -->             
     <http pattern="/js/**" security="none"/>  
     <http use-expressions="true" auto-config="true">  
           
         <form-login />  
         <logout/>  
         <!-- 实现免登陆验证 -->  
         <remember-me />  
         <session-management invalid-session-url="/timeout.jsp">  
             <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />  
         </session-management>  
         <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>  
     </http>  
     <!-- 配置过滤器 -->  
     <beans:bean id="myFilter" class="com.huaxin.security.MySecurityFilter">  
         <!-- 用户拥有的权限 -->  
         <beans:property name="authenticationManager" ref="myAuthenticationManager" />  
         <!-- 用户是否拥有所请求资源的权限 -->  
         <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />  
         <!-- 资源与权限对应关系 -->  
         <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />  
     </beans:bean>  
     <!-- 实现了UserDetailsService的Bean -->  
     <authentication-manager alias="myAuthenticationManager">  
         <authentication-provider user-service-ref="myUserDetailServiceImpl" />  
     </authentication-manager>  
     <beans:bean id="myAccessDecisionManager" class="com.huaxin.security.MyAccessDecisionManager"></beans:bean>  
     <beans:bean id="mySecurityMetadataSource" class="com.huaxin.security.MySecurityMetadataSource">  
         <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg>  
     </beans:bean>  
     <beans:bean id="myUserDetailServiceImpl" class="com.huaxin.security.MyUserDetailServiceImpl">  
         <beans:property name="usersDao" ref="usersDao"></beans:property>  
     </beans:bean>  
 </beans:beans>  
<?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.1.xsd"> <global-method-security pre-post-annotations="enabled" /> <!-- 该路径下的资源不用过滤 --> <http pattern="/js/**" security="none"/> <http use-expressions="true" auto-config="true"> <form-login /> <logout/> <!-- 实现免登陆验证 --> <remember-me /> <session-management invalid-session-url="/timeout.jsp"> <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" /> </session-management> <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </http> <!-- 配置过滤器 --> <beans:bean id="myFilter" class="com.huaxin.security.MySecurityFilter"> <!-- 用户拥有的权限 --> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <!-- 用户是否拥有所请求资源的权限 --> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <!-- 资源与权限对应关系 --> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean> <!-- 实现了UserDetailsService的Bean --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="myUserDetailServiceImpl" /> </authentication-manager> <beans:bean id="myAccessDecisionManager" class="com.huaxin.security.MyAccessDecisionManager"></beans:bean> <beans:bean id="mySecurityMetadataSource" class="com.huaxin.security.MySecurityMetadataSource"> <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg> </beans:bean> <beans:bean id="myUserDetailServiceImpl" class="com.huaxin.security.MyUserDetailServiceImpl"> <beans:property name="usersDao" ref="usersDao"></beans:property> </beans:bean> </beans:beans> 
 
我们在第二个http标签下配置一个我们自定义的继承了org.springframework.security.access.intercept.AbstractSecurityInterceptor的Filter,并注入其
必须的3个组件authenticationManager、accessDecisionManager和securityMetadataSource。其作用上面已经注释了。
 
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> 这里的FILTER_SECURITY_INTERCEPTOR是Spring Security默认的Filter,
我们自定义的Filter必须在它之前,过滤客服请求。接下来看下我们最主要的myFilter吧。
 
3)myFilter
  (1) MySecurityFilter.java 过滤用户请求
  
[java] view plaincopyprint?
public class MySecurityFilter extends AbstractSecurityInterceptor implements Filter {  
     //与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,   
     //其他的两个组件,已经在AbstractSecurityInterceptor定义   
     private FilterInvocationSecurityMetadataSource securityMetadataSource;  
   
     @Override  
     public SecurityMetadataSource obtainSecurityMetadataSource() {  
         return this.securityMetadataSource;  
     }  
   
     public void doFilter(ServletRequest request, ServletResponse response,  
             FilterChain chain) throws IOException, ServletException {  
         FilterInvocation fi = new FilterInvocation(request, response, chain);  
         invoke(fi);  
     }  
       
     private void invoke(FilterInvocation fi) throws IOException, ServletException {  
         // object为FilterInvocation对象   
                   //super.beforeInvocation(fi);源码   
         //1.获取请求资源的权限   
         //执行Collection<ConfigAttribute> attributes = SecurityMetadataSource.getAttributes(object);   
         //2.是否拥有权限   
         //this.accessDecisionManager.decide(authenticated, object, attributes);   
         InterceptorStatusToken token = super.beforeInvocation(fi);  
         try {  
             fi.getChain().doFilter(fi.getRequest(), fi.getResponse());  
         } finally {  
             super.afterInvocation(token, null);  
         }  
     }  
   
     public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {  
         return securityMetadataSource;  
     }  
   
     public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {  
         this.securityMetadataSource = securityMetadataSource;  
     }  
       
     public void init(FilterConfig arg0) throws ServletException {  
         // TODO Auto-generated method stub   
     }  
       
     public void destroy() {  
         // TODO Auto-generated method stub   
           
     }  
   
     @Override  
     public Class<? extends Object> getSecureObjectClass() {  
         //下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误   
         return FilterInvocation.class;  
     }  
 }  
public class MySecurityFilter extends AbstractSecurityInterceptor implements Filter { //与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应, //其他的两个组件,已经在AbstractSecurityInterceptor定义 private FilterInvocationSecurityMetadataSource securityMetadataSource; @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } private void invoke(FilterInvocation fi) throws IOException, ServletException { // object为FilterInvocation对象 //super.beforeInvocation(fi);源码 //1.获取请求资源的权限 //执行Collection<ConfigAttribute> attributes = SecurityMetadataSource.getAttributes(object); //2.是否拥有权限 //this.accessDecisionManager.decide(authenticated, object, attributes); InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { return securityMetadataSource; } public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } public void destroy() { // TODO Auto-generated method stub } @Override public Class<? extends Object> getSecureObjectClass() { //下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误 return FilterInvocation.class; } } 
  核心的InterceptorStatusToken token = super.beforeInvocation(fi);会调用我们定义的accessDecisionManager:decide(Object object)和securityMetadataSource
  :getAttributes(Object object)方法。
 
 (2)MySecurityMetadataSource.java
  
[java] view plaincopyprint?
//1 加载资源与权限的对应关系   
 public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {  
     //由spring调用   
     public MySecurityMetadataSource(ResourcesDao resourcesDao) {  
         this.resourcesDao = resourcesDao;  
         loadResourceDefine();  
     }  
   
     private ResourcesDao resourcesDao;  
     private static Map<String, Collection<ConfigAttribute>> resourceMap = null;  
   
     public ResourcesDao getResourcesDao() {  
         return resourcesDao;  
     }  
   
     public void setResourcesDao(ResourcesDao resourcesDao) {  
         this.resourcesDao = resourcesDao;  
     }  
   
     public Collection<ConfigAttribute> getAllConfigAttributes() {  
         // TODO Auto-generated method stub   
         return null;  
     }  
   
     public boolean supports(Class<?> clazz) {  
         // TODO Auto-generated method stub   
         return true;  
     }  
     //加载所有资源与权限的关系   
     private void loadResourceDefine() {  
         if(resourceMap == null) {  
             resourceMap = new HashMap<String, Collection<ConfigAttribute>>();  
             List<Resources> resources = this.resourcesDao.findAll();  
             for (Resources resource : resources) {  
                 Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();  
                                 //以权限名封装为Spring的security Object   
                 ConfigAttribute configAttribute = new SecurityConfig(resource.getName());  
                 configAttributes.add(configAttribute);  
                 resourceMap.put(resource.getUrl(), configAttributes);  
             }  
         }  
           
         Set<Entry<String, Collection<ConfigAttribute>>> resourceSet = resourceMap.entrySet();  
         Iterator<Entry<String, Collection<ConfigAttribute>>> iterator = resourceSet.iterator();  
           
     }  
     //返回所请求资源所需要的权限   
     public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {  
           
         String requestUrl = ((FilterInvocation) object).getRequestUrl();  
         System.out.println("requestUrl is " + requestUrl);  
         if(resourceMap == null) {  
             loadResourceDefine();  
         }  
         return resourceMap.get(requestUrl);  
     }  
   
 }  
//1 加载资源与权限的对应关系 public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource { //由spring调用 public MySecurityMetadataSource(ResourcesDao resourcesDao) { this.resourcesDao = resourcesDao; loadResourceDefine(); } private ResourcesDao resourcesDao; private static Map<String, Collection<ConfigAttribute>> resourceMap = null; public ResourcesDao getResourcesDao() { return resourcesDao; } public void setResourcesDao(ResourcesDao resourcesDao) { this.resourcesDao = resourcesDao; } public Collection<ConfigAttribute> getAllConfigAttributes() { // TODO Auto-generated method stub return null; } public boolean supports(Class<?> clazz) { // TODO Auto-generated method stub return true; } //加载所有资源与权限的关系 private void loadResourceDefine() { if(resourceMap == null) { resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); List<Resources> resources = this.resourcesDao.findAll(); for (Resources resource : resources) { Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>(); //以权限名封装为Spring的security Object ConfigAttribute configAttribute = new SecurityConfig(resource.getName()); configAttributes.add(configAttribute); resourceMap.put(resource.getUrl(), configAttributes); } } Set<Entry<String, Collection<ConfigAttribute>>> resourceSet = resourceMap.entrySet(); Iterator<Entry<String, Collection<ConfigAttribute>>> iterator = resourceSet.iterator(); } //返回所请求资源所需要的权限 public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { String requestUrl = ((FilterInvocation) object).getRequestUrl(); System.out.println("requestUrl is " + requestUrl); if(resourceMap == null) { loadResourceDefine(); } return resourceMap.get(requestUrl); } } 
 这里的resourcesDao,熟悉Dao设计模式和Spring 注入的朋友应该看得明白。
 
(3)MyUserDetailServiceImpl.java
  
[java] view plaincopyprint?
public class MyUserDetailServiceImpl implements UserDetailsService {  
       
     private UsersDao usersDao;  
     public UsersDao getUsersDao() {  
         return usersDao;  
     }  
   
     public void setUsersDao(UsersDao usersDao) {  
         this.usersDao = usersDao;  
     }  
       
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
         System.out.println("username is " + username);  
         Users users = this.usersDao.findByName(username);  
         if(users == null) {  
             throw new UsernameNotFoundException(username);  
         }  
         Collection<GrantedAuthority> grantedAuths = obtionGrantedAuthorities(users);  
           
         boolean enables = true;  
         boolean accountNonExpired = true;  
         boolean credentialsNonExpired = true;  
         boolean accountNonLocked = true;  
           
         User userdetail = new User(users.getAccount(), users.getPassword(), enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths);  
         return userdetail;  
     }  
       
     //取得用户的权限   
     private Set<GrantedAuthority> obtionGrantedAuthorities(Users user) {  
         Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();  
         Set<Roles> roles = user.getRoles();  
           
         for(Roles role : roles) {  
             Set<Resources> tempRes = role.getResources();  
             for(Resources res : tempRes) {  
                 authSet.add(new GrantedAuthorityImpl(res.getName()));  
 s           }  
         }  
         return authSet;  
     }  
 }  
public class MyUserDetailServiceImpl implements UserDetailsService { private UsersDao usersDao; public UsersDao getUsersDao() { return usersDao; } public void setUsersDao(UsersDao usersDao) { this.usersDao = usersDao; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("username is " + username); Users users = this.usersDao.findByName(username); if(users == null) { throw new UsernameNotFoundException(username); } Collection<GrantedAuthority> grantedAuths = obtionGrantedAuthorities(users); boolean enables = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; User userdetail = new User(users.getAccount(), users.getPassword(), enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths); return userdetail; } //取得用户的权限 private Set<GrantedAuthority> obtionGrantedAuthorities(Users user) { Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>(); Set<Roles> roles = user.getRoles(); for(Roles role : roles) { Set<Resources> tempRes = role.getResources(); for(Resources res : tempRes) { authSet.add(new GrantedAuthorityImpl(res.getName())); s } } return authSet; } } 
 
(4) MyAccessDecisionManager.java
[java] view plaincopyprint?
public class MyAccessDecisionManager implements AccessDecisionManager {  
       
     public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {  
         if(configAttributes == null) {  
             return;  
         }  
         //所请求的资源拥有的权限(一个资源对多个权限)   
         Iterator<ConfigAttribute> iterator = configAttributes.iterator();  
         while(iterator.hasNext()) {  
             ConfigAttribute configAttribute = iterator.next();  
             //访问所请求资源所需要的权限   
             String needPermission = configAttribute.getAttribute();  
             System.out.println("needPermission is " + needPermission);  
             //用户所拥有的权限authentication   
             for(GrantedAuthority ga : authentication.getAuthorities()) {  
                 if(needPermission.equals(ga.getAuthority())) {  
                     return;  
                 }  
             }  
         }  
         //没有权限   
         throw new AccessDeniedException(" 没有权限访问! ");  
     }  
   
     public boolean supports(ConfigAttribute attribute) {  
         // TODO Auto-generated method stub   
         return true;  
     }  
   
     public boolean supports(Class<?> clazz) {  
         // TODO Auto-generated method stub   
         return true;  
     }  
       
 }  
public class MyAccessDecisionManager implements AccessDecisionManager { public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(configAttributes == null) { return; } //所请求的资源拥有的权限(一个资源对多个权限) Iterator<ConfigAttribute> iterator = configAttributes.iterator(); while(iterator.hasNext()) { ConfigAttribute configAttribute = iterator.next(); //访问所请求资源所需要的权限 String needPermission = configAttribute.getAttribute(); System.out.println("needPermission is " + needPermission); //用户所拥有的权限authentication for(GrantedAuthority ga : authentication.getAuthorities()) { if(needPermission.equals(ga.getAuthority())) { return; } } } //没有权限 throw new AccessDeniedException(" 没有权限访问! "); } public boolean supports(ConfigAttribute attribute) { // TODO Auto-generated method stub return true; } public boolean supports(Class<?> clazz) { // TODO Auto-generated method stub return true; } } 
 
三、流程
 1)容器启动(MySecurityMetadataSource:loadResourceDefine加载系统资源与权限列表)
 2)用户发出请求
 3)过滤器拦截(MySecurityFilter:doFilter)
 4)取得请求资源所需权限(MySecurityMetadataSource:getAttributes)
 5)匹配用户拥有权限和请求权限(MyAccessDecisionManager:decide),如果用户没有相应的权限,
     执行第6步,否则执行第7步。
 6)登录
 7)验证并授权(MyUserDetailServiceImpl:loadUserByUsername)
 8)重复4,5
 
四、结束语
好了,终于写完了,回头看了一下,感觉不是怎么行。等我弄明白Spring Security它的原理之后,再回头修改下注释吧。大家觉得不妥的地方,可以留言,我会回复大家的。

我已经把源码上传到CSDN了。http://download.csdn.net/source/3283687

db_table--Spring Security3.1 最新配置实例的更多相关文章

  1. Spring AOP基于xml配置实例

    SpringAOP里的几个术语,什么切面,切点之类的,官方的说明太抽象.为了更好地理解记忆,这里几下我自己的通俗的理解. 切面:就是日记类,什么前置通知后置通知(这些都是所谓的Advice)的具体方法 ...

  2. spring aop xml中配置实例

    http://blog.csdn.net/wangpeng047/article/details/8560694

  3. 使用Spring Security3的四种方法概述

    使用Spring Security3的四种方法概述 那么在Spring Security3的使用中,有4种方法: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中,已经实现过, ...

  4. Spring Security3学习实例

    Spring Security是什么? Spring Security,这是一种基于Spring AOP和Servlet过滤器的安全框架.它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理 ...

  5. spring注解配置实例

    在spring中使用注解配置前需要先在配置文件指定需要扫描的包. 通过注解的方式依赖注入,可以不用创建set方法,也不用在xml文件中申明注入关系. 实例结构如下: 整个流程是: 先创建好数据库的表对 ...

  6. Spring Security3详细配置

    Spring Security3详细配置 表名:RESOURCE 解释:资源表备注: 资源表 RESOURCE(资源表) 是否主键 字段名 字段描述 数据类型 长度 可空 约束 缺省值 备注 是 ID ...

  7. spring security3.1配置比较纠结的2个问题

    转自:http://www.iteye.com/topic/1122629 总论无疑问的,spring security在怎么保护网页应用安全上做得很强很周全,但有些地方还是很差强人意,比如对< ...

  8. Spring Cloud Config的配置中心获取不到最新配置信息的问题

    Spring Cloud Config的配置中心获取不到最新配置信息的问题 http://blog.didispace.com/spring-cloud-tips-config-tmp-clear/

  9. Spring多数据源的配置和使用

    1. 配置多个数据源 最近开发一个数据同步的小功能,需要从A主机的Oracle数据库中把数据同步到B主机的Oracle库中.当然能够用dmp脚本或者SQL脚本是最好,但是对于两边异构的表结构来说,直接 ...

随机推荐

  1. 在Web应用程序中执行计划任务(多线程)

    在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务.实现计划任务的方法也有很多,可以采用SQ ...

  2. Safari不兼容Javascript中的Date问题

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象,但是在IOS5版本里面的Safari解释new ...

  3. 【转】TensorFlow四种Cross Entropy算法实现和应用

    http://www.jianshu.com/p/75f7e60dae95 作者:陈迪豪 来源:CSDNhttp://dataunion.org/26447.html 交叉熵介绍 交叉熵(Cross ...

  4. echarts文档对照

    echarts的各种配置项可以对照这个文档: https://echarts.baidu.com/echarts2/doc/option.html#title~tooltip.axisPointer. ...

  5. (文档)流媒体资源 Streaming Assets

    Most assets in Unity are combined into the project when it is built. However, it is sometimes useful ...

  6. LXC 容器集chroot使用说明

    1.1 LXC是什么? 1.1.1 关于LXC LXC,其名称来自Linux软件容器(Linux Containers)的缩写,一种操作系统层虚拟化(Operating system–level vi ...

  7. 查看oracle的sql语句历史记录和锁表的情况

    查看oracle的sql语句历史记录和锁表的情况 (2012-01-04 20:59:59) 转载▼ 标签: 杂谈 分类: database 查询sql的历史记录 select * from v$sq ...

  8. Activity设置Dialog属性点击区域外消失实现方式

    通过配置:<item name="android:windowCloseOnTouchOutside">true</item> 通过代码:setFinish ...

  9. Solidworks直接打开SWB文件报错怎么办

       

  10. Tomcat8配置进入管理端

    1:修改tomcat-users.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <tomcat ...