REST API 基於ACCESS TOKEN 的權限解決方案

REST token 找到用戶,而後找到用戶資源java

但總不能每一個方法都去調用token驗證的方法在進入controller前集中處理,用 Interceptor實現spring

  • 因爲根據tokenapi

    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

    <!--過濾器-->
    <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)app

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

    加入ehcache.xml,大部分都是默認,參考springside裏面說的,改了updateCheck="false",ide

    <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配置文件中加入:spa

    <!-- 緩存配置 -->
    <!-- 啓用緩存註解功能(請將其配置在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註解:debug

    @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出現xml

  • 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也緩存起來了

相關文章
相關標籤/搜索