• REST API 基于ACCESS TOKEN 的权限解决方案


    REST token 找到用户,然后找到用户资源

    但总不能每个方法都去调用token验证的方法在进入controller前集中处理,用 Interceptor实现

    • 由于根据token

      interceptor实现:

      /**
       * 验证token有效性
       */
      @Component
      public class AccessTokenVerifyInterceptor extends HandlerInterceptorAdapter {
          @Resource
          UserService userService;
      
          private final static Logger LOG = LoggerFactory.getLogger(AccessTokenVerifyInterceptor.class);
      
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                  throws Exception {
              LOG.debug("AccessTokenVerifyInterceptor executing.......");
              boolean flag = false;
              //accesstoken 参数
              String accessToken = request.getParameter("accesstoken");
              if(StringUtils.notEmpty(accessToken)) {
                  //验证accessToken
                  //verifyAccessToken 已做缓存处理
                  User user = userService.verifyAccessToken(accessToken);
                  if(user!=null){
                      flag = true;
                      //塞到request中去,供controller里面调用
                      request.setAttribute(SystemConstants.SESSION_NAME_USER,user);
                  }
              }
      
              if(!flag){
                  response.setStatus(HttpStatus.FORBIDDEN.value());
                  response.getWriter().print("wrong token");
              }
              return flag;
          }
      }

      然后到spring配置文件中加上这个拦截器:

      <!--过滤器-->
      <mvc:interceptors>
          <!--API TOKEN INTERCEPTOR-->
          <mvc:interceptor>
              <mvc:mapping path="/api/**"/>
              <mvc:exclude-mapping path="/**/api/user/**" />
              <mvc:exclude-mapping path="/**/api/accesstoken" />
              <bean class="cn.ifengkou.athena.controller.interceptor.AccessTokenVerifyInterceptor"></bean>
          </mvc:interceptor>
          <!--other interceptor -->
      </mvc:interceptors>

      缓存处理

      pom.xml中加入ehcache包:(spring集成ehcache ,需要spring-context和spring-context-support)

              <dependency>
                  <groupId>net.sf.ehcache</groupId>
                  <artifactId>ehcache</artifactId>
                  <version>2.10.0</version>
              </dependency>

      加入ehcache.xml,大部分都是默认,参考springside里面说的,改了updateCheck="false",

      <ehcache updateCheck="false"
               monitoring="autodetect"
               dynamicConfig="true">
          <diskStore path="java.io.tmpdir" />
          <cache name="accessTokenUser"
                 maxEntriesLocalHeap="10000"
                 maxEntriesLocalDisk="1000"
                 eternal="false"
                 diskSpoolBufferSizeMB="20"
                 timeToIdleSeconds="300" timeToLiveSeconds="600"
                 memoryStoreEvictionPolicy="LFU"
                 transactionalMode="off">
              <persistence strategy="localTempSwap" />
          </cache>
      </ehcache>

      开启缓存,在spring配置文件中加入:

      <!-- 缓存配置 -->
      <!-- 启用缓存注解功能(请将其配置在Spring主配置文件中) -->
      <cache:annotation-driven cache-manager="cacheManager" />
      
      <!-- Spring自己的基于java.util.concurrent.ConcurrentHashMap实现的缓存管理器(该功能是从Spring3.1开始提供的) -->
      <!-- <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
          <property name="caches"> <set> <bean name="myCache" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"/>
          </set> </property> </bean> -->
      <!-- 若只想使用Spring自身提供的缓存器,则注释掉下面的两个关于Ehcache配置的bean,并启用上面的SimpleCacheManager即可 -->
      <!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
      <bean id="cacheManagerFactory"
            class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
          <property name="configLocation" value="classpath:ehcache.xml" />
      </bean>
      <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
          <property name="cacheManager" ref="cacheManagerFactory" />
      </bean>

      对verifyAccessToken 方法做缓存处理,也就是在原有方法上加Cacheable注解:

      @Cacheable(value = "accessTokenUser",key = "#accessToken")
      @Override
      public User verifyAccessToken(String accessToken) {
          LOG.debug("verifyAccessToken executing......");
          List<User> users = userDao.getUserByAccessToken(accessToken);
          if(users.size()!=1){
              if(users.size()>1){
                  LOG.error("accessToken 出现了重复,bug!请检查!");
              }
              return null;
          }
          return users.get(0);
      }

      开始run出现

    • 2015-12-04 15:25:56,531 INFO [cn.ifengkou.athena.controller.interceptor.AccessTokenVerifyInterceptor] - <AccessTokenVerifyInterceptor executing.......>
      2015-12-04 15:25:56,628 INFO [cn.ifengkou.athena.service.impl.UserServiceImpl] - <verifyAccessToken executing......>
      2015-12-04 15:26:21,838 INFO [cn.ifengkou.athena.controller.interceptor.AccessTokenVerifyInterceptor] - <AccessTokenVerifyInterceptor executing.......>
      2015-12-04 15:26:29,184 INFO [cn.ifengkou.athena.controller.interceptor.AccessTokenVerifyInterceptor] - <AccessTokenVerifyInterceptor executing.......>
      
    • 如有token无效,查出来User为null,cache 把null也缓存起来了

  • 相关阅读:
    Redis5设计与源码分析 (第17章 HyperLogLog相关命令的实现)
    Redis5设计与源码分析 (第16章 GEO相关命令)
    ES5和ES6函数的this指向
    vue响应式原理 (响应式并不等于数据双向绑定,千万不要混淆)
    vue中data为什么是函数而不是对象
    vue-enum 前端常量 枚举工具
    Vue3 写业务逻辑不适合用TS(TypeScript)
    vue-property-decorator vue3 ts 用的装饰器
    github git clone下载加速 && npm install 下载加速
    vue3 如果用ts,导出时候要用 defineComponent,这俩是配对的,为了类型的审查正确
  • 原文地址:https://www.cnblogs.com/toSeeMyDream/p/5805490.html
Copyright © 2020-2023  润新知