spring AOP 自己實現(xiàn)一個手機授權(quán)

2016.7.11 4:32

如今很多后臺涉及很多手機登錄授權(quán)管理,很多人使用shiro 或者spring security 解決,其中shiro 接入比較簡單,但是security 接入入門水平就比較高了。如果不想接入任何的登錄授權(quán)的話,啃官方文檔的話。那就對了。接下來我們就結(jié)合spring AOP 來寫一個簡單的token管理,自定義注解來解決此授權(quán)問題。主要分為下面的幾個步驟:

  1. tokenManager 的建立
  2. 自定義注解的建立
  3. 實現(xiàn)一個和User一樣的類
  4. 結(jié)合AOP來解決節(jié)省多余的代碼。
  5. 體驗一下我們的tokenValid 的使用吧。

寫一個具有時效性的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);
    }

}

然后我們只要在每個需要登錄的接口處,判斷獲取userId 并且判斷數(shù)據(jù)庫內(nèi)是否存在該用戶即可。這時候AOP就派上用場了。不哆嗦我們來結(jié)合AOP來完成一個token認證吧。

自定義token
/**
 * Created by zengfeng on 16/6/30.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenValid {

}
實現(xiàn)一個和User一樣的類(至于為什么這么干,我是想當修改用戶信息的時候傳遞參數(shù)對象和我們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, "請重新登錄");
        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);
    }

}
下面我們來體驗一下我們的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 是不是很好玩?各位兄弟姐妹們。喜歡的點贊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容