1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        實(shí)戰(zhàn):十分鐘實(shí)現(xiàn)基于JWT前后端分離的權(quán)限框架

        共 6920字,需瀏覽 14分鐘

         ·

        2020-08-26 15:39

        前言

        面試過(guò)很多Java開發(fā),能把權(quán)限這塊說(shuō)的清楚的實(shí)在是不多,很多人因?yàn)楣卷?xiàng)目職責(zé)問題,很難學(xué)到這類相關(guān)的流程和技術(shù),本文梳理一個(gè)簡(jiǎn)單的場(chǎng)景,實(shí)現(xiàn)一個(gè)基于jwt前后端分離的權(quán)限框架。

        簡(jiǎn)易流程

        登錄獲取票據(jù)和緩存信息

        image-20200709160301317

        鑒權(quán)流程

        image-20200709160427929

        技術(shù)棧和功能規(guī)劃

        本文技術(shù)選型為SpringBoot+JWT+Redis, 實(shí)現(xiàn)上圖的登錄流程和鑒權(quán)流程,并提供完整項(xiàng)目代碼。

        「本項(xiàng)目已實(shí)現(xiàn)如下功能」

        • 跨域配置
        • jwt集成
        • redis集成
        • BaseController封裝,方便取出用戶信息
        • 攔截器和白名單
        • 全局異常
        • jwt工具類封裝
        • redis工具類封裝
        • redis枚舉Key封裝

        Redis安裝和啟動(dòng)

        使用Docker一行命令構(gòu)建啟動(dòng)Redis,命令如下

        ?docker?run?-itd?--name?redis-test?-p?6379:6379?redis?--requirepass?"123456redis"

        指定端口:6379

        指定密碼:123456redis

        客戶端連接測(cè)試,問題不大~

        創(chuàng)建SpringBoot項(xiàng)目并引入JWT依賴


        ??io.jsonwebtoken
        ??jjwt
        ??0.9.1

        其實(shí)主要是引了這個(gè)包,其他的就不貼出來(lái)了。主要有redis以及json相關(guān)的,完整代碼都在項(xiàng)目可以自己看

        寫一個(gè)登陸方法

        UserController

        ??@PostMapping("/login")
        ????public?UserVO?login(@RequestBody?LoginDTO?loginDTO)??{
        ????????return?userService.login(loginDTO);
        ????}

        UserService

        用戶信息就模擬的了,都看的懂。登錄成功后根據(jù)uid生產(chǎn)jwt,然后緩存到redis,封裝結(jié)果給到前端

        package?com.lzp.auth.service;

        @Service
        public?class?UserService?{

        ????@Value("${server.session.timeout:3000}")
        ????private?Long?timeout;

        ????@Autowired
        ????private?RedisUtils?redisUtils;

        ????final?static?String?USER_NAME?=?"admin";

        ????//密碼?演示用就不做加密處理了
        ????final?static?String?PWD?=?"admin";


        ????public?UserVO?login(LoginDTO?loginDTO){

        ????????User?user?=?getByName(loginDTO.getUserName());

        ????????//用戶信息校驗(yàn)和查詢
        ????????if?(user?==?null){
        ????????????throw?new?ServiceException(ResultCodeEnum.LOGIN_FAIL);
        ????????}
        ????????//密碼校驗(yàn)
        ????????if(!PWD.equals(loginDTO.getPwd())){
        ????????????throw?new?ServiceException(ResultCodeEnum.LOGIN_FAIL);
        ????????}

        ????????//緩存用戶信息并設(shè)置過(guò)期時(shí)間
        ????????UserVO?userVO?=?new?UserVO();
        ????????userVO.setName(user.getName());
        ????????userVO.setUid(user.getUid());
        ????????userVO.setToken(JWTUtils.generate(user.getUid()));

        ????????//信息入庫(kù)redis
        ????????redisUtils.set(RedisKeyEnum.OAUTH_APP_TOKEN.keyBuilder(userVO.getUid()),?JSONObject.toJSONString(userVO),?timeout);

        ????????return?userVO;
        ????}
        ????/**
        ?????*?通過(guò)用戶名獲取用戶
        ?????*?@param?name
        ?????*?@return
        ?????*/

        ????public?User?getByName(String?name){
        ????????User?user?=?null;
        ????????if(USER_NAME.equals(name)){
        ????????????user?=??new?User("1","張三","Aa123456");
        ????????}
        ????????return?user;
        ????}

        }

        定義登錄攔截器

        LoginInterceptor

        package?com.lzp.auth.config;


        import?com.lzp.auth.exception.ServiceException;
        import?com.lzp.auth.utils.JWTUtils;
        import?com.lzp.auth.utils.ResultCodeEnum;
        import?com.lzp.auth.utils.SessionContext;
        import?io.jsonwebtoken.Claims;
        import?lombok.extern.slf4j.Slf4j;
        import?org.springframework.beans.factory.annotation.Autowired;
        import?org.springframework.data.redis.core.StringRedisTemplate;
        import?org.springframework.util.StringUtils;
        import?org.springframework.web.servlet.ModelAndView;
        import?org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

        import?javax.servlet.http.HttpServletRequest;
        import?javax.servlet.http.HttpServletResponse;

        @Slf4j
        public?class?LoginInterceptor?extends?HandlerInterceptorAdapter?{


        ????@Autowired
        ????StringRedisTemplate?redisTemplate;


        ????@Override
        ????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
        ????????String?token?=?request.getHeader("token");
        ????????String?requestURI?=?request.getRequestURI().replaceAll("/+",?"/");

        ????????log.info("requestURI:{}",requestURI);

        ????????if?(StringUtils.isEmpty(token))?{
        ????????????throw?new?ServiceException(ResultCodeEnum.AUTH_FAIL);
        ????????}

        ????????Claims?claim?=?JWTUtils.getClaim(token);
        ????????if(claim?==?null){
        ????????????throw?new?ServiceException(ResultCodeEnum.AUTH_FAIL);
        ????????}

        ????????String?uid?=?null;
        ????????try?{
        ????????????uid?=?JWTUtils.getOpenId(token);
        ????????}?catch?(Exception?e)?{
        ????????????throw?new?ServiceException(ResultCodeEnum.AUTH_FAIL);
        ????????}

        ????????//用戶id放到上下文?可以當(dāng)前請(qǐng)求進(jìn)行傳遞
        ????????request.setAttribute(SessionContext.USER_ID_KEY,?uid);
        ????????return?true;
        ????}


        ????@Override
        ????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{
        ????}

        ????@Override
        ????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{
        ????}


        }

        配置跨域、資源、定義攔截器、加白名單

        package?com.lzp.auth.config;

        import?org.springframework.beans.BeansException;
        import?org.springframework.context.ApplicationContext;
        import?org.springframework.context.ApplicationContextAware;
        import?org.springframework.context.annotation.Bean;
        import?org.springframework.context.annotation.Configuration;
        import?org.springframework.web.cors.CorsConfiguration;
        import?org.springframework.web.cors.reactive.CorsWebFilter;
        import?org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
        import?org.springframework.web.servlet.config.annotation.InterceptorRegistry;
        import?org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
        import?org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
        import?org.springframework.web.util.pattern.PathPatternParser;

        @Configuration
        public?class?WebMvcConfig?extends?WebMvcConfigurerAdapter?implements?ApplicationContextAware?{


        ????private?ApplicationContext?applicationContext;

        ????public?WebMvcConfig()?{
        ????????super();
        ????}

        ????@Override
        ????public?void?addResourceHandlers(ResourceHandlerRegistry?registry)?{
        ????????super.addResourceHandlers(registry);
        ????}

        ????@Override
        ????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
        ????????this.applicationContext?=?applicationContext;
        ????}

        ????@Bean
        ????public?CorsWebFilter?corsFilter()?{
        ????????CorsConfiguration?config?=?new?CorsConfiguration();
        ????????config.addAllowedMethod("*");
        ????????config.addAllowedOrigin("*");
        ????????config.addAllowedHeader("*");
        ????????UrlBasedCorsConfigurationSource?source?=?new?UrlBasedCorsConfigurationSource(new?PathPatternParser());
        ????????source.registerCorsConfiguration("/**",?config);
        ????????return?new?CorsWebFilter(source);
        ????}


        ????@Bean
        ????LoginInterceptor?loginInterceptor()?{
        ????????return?new?LoginInterceptor();
        ????}


        ????@Override
        ????public?void?addInterceptors(InterceptorRegistry?registry)?{

        ????????//攔截規(guī)則:除了login,其他都攔截判斷
        ????????registry.addInterceptor(loginInterceptor())
        ????????????????.addPathPatterns("/**")
        ????????????????.excludePathPatterns("/user/login");

        ????????super.addInterceptors(registry);
        ????}

        }

        「postMan調(diào)試」

        模擬成功和失敗場(chǎng)景

        成功如上圖,返回用戶信息和Token

        失敗如上圖

        測(cè)試非白名單接口


        「使用token再來(lái)訪問當(dāng)前接口」

        完美~

        至此本項(xiàng)目就完美結(jié)束了哦

        項(xiàng)目代碼

        https://github.com/pengziliu/GitHub-code-practice

        這個(gè)倉(cāng)庫(kù)除了這個(gè)還有更多精彩代碼喲


        已擼完部分開源輪子,更多精彩正在路上

        模塊所屬開源項(xiàng)目項(xiàng)目介紹
        springboot_api_encryptionrsa-encrypt-body-spring-bootSpring Boot接口加密,可以對(duì)返回值、參數(shù)值通過(guò)注解的方式自動(dòng)加解密 。
        simpleimage-demosimpleimage圖片處理工具類,具有加水印、壓縮、裁切等功能
        xxl-job-demoxxl-job分布式定時(shí)任務(wù)使用場(chǎng)景
        xxl-sso-demoxxl-sso單點(diǎn)登錄功能
        vuepress-demovuepress建立自己的知識(shí)檔案庫(kù)
        xxl-conf-demoxxl-conf分布式配置中心
        Shardingsphere-demoShardingsphere分庫(kù)分表
        easyexcel-demoeasyexcelexcel操作工具類

        kaptcha-demokaptcha前后端分離驗(yàn)證碼方案

        —?【 THE END 】—
        本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲??!


        3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。。?/span>




        瀏覽 71
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本三级黄色网址 | 伦理h动漫视频免费看 | 丁香五月天啪啪 | 日韩一区二区三区中文字幕 | 九色蝌蚪9l视频蝌蚪9l视频开放 | 亲子乱AⅤ一区二区三区 | 女人脱了内裤让男人捅 | 中文字幕一区二区三区四虎在线 | 人妻一区二区三区在线电影 | 五月丁香狠狠爱 |