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. 用非递归、不用栈的方法,实现原位(in-place)的快速排序

    大体思路是修改Partition方法将原本枢数的调整放到方法结束后去做.这样因为数组右侧第一个大于当前枢数的位置就应该是未划分的子数组的边界.然后继续进行Partition调整.这种写法照比递归的写法 ...

  2. Logistic Regression总结

    转自:http://blog.csdn.net/dongtingzhizi/article/details/15962797 Logistic回归总结 作者:洞庭之子 微博:洞庭之子-Bing (20 ...

  3. iOS开发-16进制颜色转换

    项目中经常会用到颜色转换,有的是通过十六进制转成数字转颜色,想简单的点直接通过字符串转一下,简单扩展了一下分类UIColor,代码如下: +(UIColor *)colorWithHex:(NSStr ...

  4. VS Code .vue文件代码缩进以及格式化代码

    首先在应用商店中搜索“Vetur”插件安装,然后进行下面操作: 文件->首选项->设置,然后在右边编辑框输入以下设置: { "prettier.tabWidth": 4 ...

  5. vue版本冲突解决办法

    ERROR in Vue packages version mismatch: vue@2.1.4 vue-template-compiler@2.1.5 This may cause things ...

  6. AOP中Advice执行两遍的原因

    在我的spring项目中,Aop的Advice执行了两边,就好像拦截了两遍一样. 原因是:切面应该切到接口的实现类上,而不是接口上

  7. [Git] Undo a commit that has already been pushed to the remote repository

    If we pushed our changes already to the remote repository we have to pay attention to not change the ...

  8. SliTaz 从入门到精通

    slitaz中文化(linux-pe)项目地址: https://code.google.com/p/linux-pe/ http://bbs.wuyou.com/forum.php?mod=view ...

  9. AS-->创建项目(慢)和打开项目(慢)等需要注意的问题

    Android Studio 创建新项目的时候,会在进度条的界面滞留很久. 有时候一天都卡在这. 打开其它项目有些时候,也会出现这种情况. 主要的原因就是, 此过程正在 下载对应版本的 gradle. ...

  10. QT 截取屏幕的实现

    QPixmap提供了两个函数 grabWidget 和 grabWindow 可以将屏幕上的窗体存成一个 QPixmap 格式的图片,很容易再将 QPixmap 存成文件.函数使用很简单,两行代码就可 ...