最近碰到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;
}
}
}