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也缓存起来了

原文地址:https://www.cnblogs.com/toSeeMyDream/p/5805490.html