2016.7.11 4:32
如今很多后臺(tái)涉及很多手機(jī)登錄授權(quán)管理,很多人使用shiro 或者spring security 解決,其中shiro 接入比較簡單扫沼,但是security 接入入門水平就比較高了。如果不想接入任何的登錄授權(quán)的話,啃官方文檔的話镊掖。那就對(duì)了。接下來我們就結(jié)合spring AOP 來寫一個(gè)簡單的token管理褂痰,自定義注解來解決此授權(quán)問題亩进。主要分為下面的幾個(gè)步驟:
- tokenManager 的建立
- 自定義注解的建立
- 實(shí)現(xiàn)一個(gè)和User一樣的類
- 結(jié)合AOP來解決節(jié)省多余的代碼。
- 體驗(yàn)一下我們的tokenValid 的使用吧脐恩。
寫一個(gè)具有時(shí)效性的tokenManager
@Component
public class TokenManager {
public static Map<String, Map<String,Object>> token = new HashMap<>();
private static Map<String, String> tokenMap = new ConcurrentHashMap<>();
public String createToken(String username) {
String token = UUID.randomUUID().toString();
tokenMap.put(token, username);
return token;
}
public Integer verifyToken(String token) {
/**
* 走后門
*/
Map<String,Object> map = new HashMap<>();
map.put("user_id", String.valueOf(15));
map.put("time",new Date().getTime());
TokenManager.token.put("1",map);
Map<String,Object> tokenMap = TokenManager.getToken(token);
if(tokenMap == null){
return null;
}
Assert.notNull(tokenMap.get("time"));
Assert.notNull(tokenMap.get("user_id"));
long time = Long.parseLong(tokenMap.get("time").toString()) ;
if (new Date().getTime() - time > 7 * 24 * 60 * 60 * 1000) {
TokenManager.token.remove(token);
return null;
}
tokenMap.put("time",new Date().getTime());
TokenManager.setToken(token,tokenMap);
return Integer.parseInt(tokenMap.get("user_id").toString());
}
public boolean checkToken(String token) {
return !StringUtils.isEmpty(token) && tokenMap.containsKey(token);
}
public synchronized String createToken(){
return UUID.randomUUID().toString().replace("-","");
}
public static Map<String, Map<String,Object>> getToken() {
return token;
}
public static Map<String,Object> getToken(String token) {
return TokenManager.token.get(token);
}
public synchronized static void setToken(String token,Map<String, Object> map) {
TokenManager.token.put(token,map);
}
}
然后我們只要在每個(gè)需要登錄的接口處镐侯,判斷獲取userId 并且判斷數(shù)據(jù)庫內(nèi)是否存在該用戶即可。這時(shí)候AOP就派上用場了驶冒。不哆嗦我們來結(jié)合AOP來完成一個(gè)token認(rèn)證吧苟翻。
自定義token
/**
* Created by zengfeng on 16/6/30.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenValid {
}
實(shí)現(xiàn)一個(gè)和User一樣的類(至于為什么這么干,我是想當(dāng)修改用戶信息的時(shí)候傳遞參數(shù)對(duì)象和我們token管理的user信息區(qū)分開來骗污。)
public class Principle{
private String userName;
private String password;
/** 忽略屬性和getter setter 方法 */
}
Spring Aop 的使用
@Aspect
@Order(10)
@Configuration
public class TokenAop {
@Autowired
TokenManager tokenManager;
@Autowired
AsUserMapper asUserMapper;
@Autowired
HttpServletRequest request;
@Pointcut("execution(* com.zf.controller.*.*(..))&&" + "@annotation(com.zf.config.TokenValid)")
public void tokenPointCut() {
}
@Around(value = "tokenPointCut()")
public Object addTokenToMethod(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Object token = request.getParameter("token");
AsUser asUser = findUser(args,token);
Assert.notNull(asUser, "請(qǐng)重新登錄");
injectUserObject(asUser, args,token);
return joinPoint.proceed(args);
}
private void injectUserObject(AsUser asUser, Object[] args,Object token) {
for (int i=0; i < args.length;i++)
if (args[i] instanceof Principle) {
args[i] = userConvertPrinciple(asUser);
break;
}
}
/**
* @param u
* @return
*/
private Object userConvertPrinciple(AsUser u) {
Principle principle = new Principle();
BeanUtils.copyProperties(u,principle);
return principle;
}
private AsUser findUser(Object[] args, Object token) {
Integer userId = tokenManager.verifyToken((String) token);
return asUserMapper.selectByPrimaryKey(userId);
}
}
下面我們來體驗(yàn)一下我們的tokenValid 的使用吧崇猫。
@RestController
@RequestMapping("/api/user")
public class UserController {
@TokenValid
@RequestMapping(value = "/setDefaultAddress",method = RequestMethod.POST)
public void setDefaultAddress(Principle principle,@RequestParam Integer uadId) throws ExpireException, NotSamePeopleException {
usersService.save(principle, uadId);
};
?? spring 是不是很好玩?各位兄弟姐妹們需忿。喜歡的點(diǎn)贊诅炉。