Spring AOP自定義註解 身份驗證

最近碰到APP開發權限驗證的問題 用過濾器不能解決某些無需驗證的方法 所以最終選擇用AOP 解決

代碼如下定義一個權限註解

package com.thinkgem.jeesite.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 權限註解
 * Created by Hamming on 2016/12/26.
 */
@Target(ElementType.METHOD)//這個註解是應用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessToken {
/*    String userId();
    String token();*/
}
獲取頁面請求中的ID token

@Aspect
@Component
public class AccessTokenAspect {

    @Autowired
    private ApiService apiService;

    @Around("@annotation(com.thinkgem.jeesite.common.annotation.AccessToken)")
    public Object doAccessCheck(ProceedingJoinPoint pjp) throws Throwable{
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String id = request.getParameter("id");
        String token = request.getParameter("token");
        boolean verify = apiService.verifyToken(id,token);
        if(verify){
            Object object = pjp.proceed(); //執行連接點方法
            //獲取執行方法的參數

            return object;
        }else {
            return ResultApp.error(3,"token失效");
        }
    }
}

token驗證類  存儲用到redis

package com.thinkgem.jeesite.common.service;

import com.thinkgem.jeesite.common.utils.JedisUtils;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import java.io.*;
import java.security.Key;
import java.util.Date;

/**
 *token登陸驗證
 * Created by Hamming on 2016/12/23.
 */
@Service
public class ApiService {
    private static final String at="accessToken";

    public static Key key;

//    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 生成token
     * Key以字節流形式存入redis
     *
     * @param date  失效時間
     * @param appId AppId
     * @return
     */
    public String generateToken(Date date, String appId){
        Jedis jedis = null;
        try {
            jedis = JedisUtils.getResource();
            byte[] buf = jedis.get("api:key".getBytes());
            if (buf == null) { // 建新的key
                key = MacProvider.generateKey();
                ByteArrayOutputStream bao = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bao);
                oos.writeObject(key);
                buf = bao.toByteArray();
                jedis.set("api:key".getBytes(), buf);
            } else { // 重用老key
                key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();
            }

        }catch (IOException io){
//            System.out.println(io);
        }catch (ClassNotFoundException c){
//            System.out.println(c);
        }catch (Exception e) {
//            logger.error("ApiService", "generateToken", key, e);
        } finally {
            JedisUtils.returnResource(jedis);
        }

        String token = Jwts.builder()
                .setSubject(appId)
                .signWith(SignatureAlgorithm.HS512, key)
                .setExpiration(date)
                .compact();
        // 計算失效秒,7889400秒三個月
        Date temp = new Date();
        long interval = (date.getTime() - temp.getTime())/1000;
        JedisUtils.set(at+appId ,token,(int)interval);
        return token;
    }

    /**
     * 驗證token
     * @param appId AppId
     * @param token token
     * @return
     */
    public boolean verifyToken(String appId, String token) {
        if( appId == null|| token == null){
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = JedisUtils.getResource();
            if (key == null) {
                byte[] buf = jedis.get("api:key".getBytes());
                if(buf==null){
                    return false;
                }
                key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();
            }
            Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody().getSubject().equals(appId);
            return true;
        } catch (Exception e) {
//            logger.error("ApiService", "verifyToken", key, e);
            return false;
        } finally {
            JedisUtils.returnResource(jedis);
        }
    }

    /**
     * 獲取token
     * @param appId
     * @return
     */
    public String getToken(String appId) {
        Jedis jedis = null;
        try {
            jedis = JedisUtils.getResource();
            return jedis.get(at+appId);
        } catch (Exception e) {
//            logger.error("ApiService", "getToken", e);
            return "";
        } finally {
            JedisUtils.returnResource(jedis);
        }
    }
}

spring aop配置 
    <!--aop -->
    <!--      掃描註解bean -->
    <context:component-scan base-package="com.thinkgem.jeesite.common.aspect"/>
    <aop:aspectj-autoproxy proxy-target-class="true"/>


驗證權限方法使用 直接用註解就可以了AccessToken

例如

package com.thinkgem.jeesite.modules.app.web.pay;

import com.alibaba.fastjson.JSON;
import com.thinkgem.jeesite.common.annotation.AccessToken;
import com.thinkgem.jeesite.common.base.ResultApp;
import com.thinkgem.jeesite.modules.app.service.pay.AppAlipayConfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

/**
 * 支付接口
 * Created by Hamming on 2016/12/27.
 */
@Controller
@RequestMapping(value = "/app/pay")
public class AppPayModule {

    @Autowired
    private AppAlipayConfService appAlipayConfService;

    @RequestMapping(value = "/alipay", method = RequestMethod.POST, produces="application/json")
    @AccessToken
    @ResponseBody
    public Object alipay(String orderId){
        if(orderId ==null){
            Map re = new HashMap<>();
            re.put("result",3);
            re.put("msg","參數錯誤");
            String json = JSON.toJSONString(re);
            return json;
        }else {
            return null;
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章