springSecurity入门笔记(三)

缓存UserDetails

CachingUserDetailsService类的构造接收一个用于真正加载UserDetails的UserDetailsService实现类。
当需要加载UserDetails时,其首先会从缓存中获取,如果缓存中没有对应的UserDetails存在,则使用持有的UserDetailsService实现类进行加载,然后将加载后的结果存放在缓存中。
UserDetails与缓存的交互是通过UserCache接口来实现的。
当我们需要对UserDetails进行缓存时,我们只需要定义一个Ehcache实例,然后把它注入给EhCacheBasedUserCache就可以了

   <security:authentication-manager alias="authenticationManager">
      <!-- 使用可以缓存UserDetails的CachingUserDetailsService -->
      <security:authentication-provider
         user-service-ref="cachingUserDetailsService" />
   </security:authentication-manager>

   <!-- 可以缓存UserDetails的UserDetailsService -->
   <bean id="cachingUserDetailsService" class="org.springframework.security.config.authentication.CachingUserDetailsService">
      <!-- 真正加载UserDetails的UserDetailsService -->
      <constructor-arg ref="userDetailsService"/>
      <!-- 缓存UserDetails的UserCache -->
      <property name="userCache">
         <bean class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
            <!-- 用于真正缓存的Ehcache对象 -->
            <property name="cache" ref="ehcache4UserDetails"/>
         </bean>
      </property>
   </bean>

   <!-- 将使用默认的CacheManager创建一个名为ehcache4UserDetails的Ehcache对象 -->
   <bean id="ehcache4UserDetails" class="org.springframework.cache.ehcache.EhCacheFactoryBean"/>

   <!-- 从数据库加载UserDetails的UserDetailsService -->
   <bean id="userDetailsService"
      class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
      <property name="dataSource" ref="dataSource" />
   </bean>

退出登录

 <security:logout logout-url="/logout.do"/>

logout其他属性

属性名作用
invalidate-session表示是否要在退出登录后让当前session失效,默认为true。
delete-cookies指定退出登录后需要删除的cookie名称,多个cookie之间以逗号分隔。
logout-success-url指定成功退出登录后要重定向的URL。需要注意的是对应的URL应当是不需要登录就可以访问的。
success-handler-ref指定用来处理成功退出登录的LogoutSuccessHandler的引用。

基于方法的权限控制

intercept-methods定义方法权限控制
<!--以find开始的方法时需要当前用户拥有ROLE_USER的权限
在执行方法名以add、update或delete开始的方法时需要拥有ROLE_ADMIN的权限-->
   <bean id="userService" class="com.xxx.service.impl.UserServiceImpl">
      <security:intercept-methods>
         <security:protect access="ROLE_USER" method="find*"/>
         <security:protect access="ROLE_ADMIN" method="add*"/>
         <security:protect access="ROLE_ADMIN" method="update*"/>
         <security:protect access="ROLE_ADMIN" method="delete*"/>
      </security:intercept-methods>
   </bean>
使用pointcut定义方法权限控制
<!--在执行com.elim包或其子包下任意以Service结尾的类,其方法名以find开始的所有方法时都需要用户拥有ROLE_READ的权限
对于com.elim包或其子包下任意以Service结尾的类的其它方法在执行时都需要ROLE_WRITE的权限-->
   <security:global-method-security>
      <security:protect-pointcut access="ROLE_READ" expression="execution(* com.elim.*..*Service.find*(..))"/>
      <security:protect-pointcut access="ROLE_WRITE" expression="execution(* com.elim.*..*Service.*(..))"/>
   </security:global-method-security>
使用注解定义方法权限控制

JSR-250注解、@Secured注解和支持表达式的注解

JSR-250注解
<security:global-method-security jsr250-annotations="enabled"/>
@Service
@RolesAllowed("ROLE_ADMIN")//所有的方法都需要角色ROLE_ADMIN
public class UserServiceImpl implements UserService {

   public void addUser(User user) {
      System.out.println("addUser................" + user);
   }

   public void updateUser(User user) {
      System.out.println("updateUser.............." + user);
   }

   @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
   public User find(int id) {
      System.out.println("find user by id............." + id);
      return null;
   }

   public void delete(int id) {
      System.out.println("delete user by id................");
   }

   @RolesAllowed("ROLE_USER")
   public List<User> findAll() {
      System.out.println("find all user...............");
      return null;
   }
}
  • @RolesAllowed:表示访问对应方法时所应该具有的角色。其可以标注在类上,也可以标注在方法上
  • @PermitAll:表示允许所有的角色进行访问。其可以标注在类上,也可以标注在方法上
  • @DenyAll:表示无论什么角色都不能访问。只能定义在方法上。脱离了权限控制还是可以访问的。

方法上的优先度高于类上的

@Secured注解
<security:global-method-security secured-annotations="enabled"/>
@Service
public class UserServiceImpl implements UserService {

   @Secured("ROLE_ADMIN")
   public void addUser(User user) {
      System.out.println("addUser................" + user);
   }

   @Secured("ROLE_USER")
   public List<User> findAll() {
      System.out.println("find all user...............");
      return null;
   }
}
支持表达式的注解

四个支持使用表达式的注解,分别是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前两者可以用来在方法调用前或者调用后进行权限检查,后两者可以用来对集合类型的参数或者返回值进行过滤。

<!--启动  enabled ,默认disabled-->
<security:global-method-security pre-post-annotations="disabled"/>

使用@PreAuthorize和@PostAuthorize进行访问控制

@Service

public class UserServiceImpl implements UserService {

	/**
	 *只有拥有角色ROLE_ADMIN的用户才能访问
	 */
   @PreAuthorize("hasRole('ROLE_ADMIN')")
   public void addUser(User user) {
      System.out.println("addUser................" + user);
   }
   
	/**
	 *有ROLE_USER角色或ROLE_ADMIN角色能访问
	 */
   @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
   public User find(int id) {
      System.out.println("find user by id............." + id);
      return null;
   } 

   /**
    * 限制只能查询Id小于10的用户
    */
   @PreAuthorize("#id<10")
   public User find(int id) {
      System.out.println("find user by id........." + id);
      return null;
   }

   /**
    * 限制只能查询自己的信息
    */
   @PreAuthorize("principal.username.equals(#username)")
   public User find(String username) {
      System.out.println("find user by username......" + username);
      return null;
   }

   /**
    * 限制只能新增用户名称为abc的用户
    */
   @PreAuthorize("#user.name.equals('abc')")
   public void add(User user) {
      System.out.println("addUser............" + user);
   }
   
   /**
    *在方法find()调用完成后进行权限检查,返回值的id是偶数则表示校验通过,否则表示校验失败
    */
   @PostAuthorize("returnObject.id%2==0")
   public User find(int id) {
      User user = new User();
      user.setId(id);
      return user;
   }
}

使用@PreFilter和@PostFilter对集合类型的参数或返回值进行过滤

	/**
	 *对返回结果中id不为偶数的user进行移除
	 *lterObject是使用@PreFilter和@PostFilter时的一个内置表达式,表示集合中的当前对象
	 */
   @PostFilter("filterObject.id%2==0")
   public List<User> findAll() {
      List<User> userList = new ArrayList<User>();
      User user;
      for (int i=0; i<10; i++) {
         user = new User();
         user.setId(i);
         userList.add(user);
      }
      return userList;
   }

当@PreFilter标注的方法拥有多个集合类型的参数时
需要通过@PreFilter的filterTarget属性指定当前@PreFilter是针对哪个参数进行过滤的

/**
 *通过filterTarget指定了当前@PreFilter是用来过滤参数ids
 */
   @PreFilter(filterTarget="ids", value="filterObject%2==0")
   public void delete(List<Integer> ids, List<String> usernames) {
      ...
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值