2.eladmin的登陸功能


后端控制登陸的Controller位置

 

 對應前端文件

 二維碼

 來看看二維碼是怎么實現的,點擊圖片觸發了getCode這個函數

 

 這個getCode函數被放在初始化函數里,可以看到具體的getCodeImg函數接收了一個img和uuid,所以我們要提供給前端的也就是uuid和img

 

 

 

調用的是這個函數,而這個函數調用了request的函數來自/utils/request,具體先不管這個函數是怎么實現的,大概意思就是指定一個方法和url就可以發送請求了

 來到后端的代碼

大體步驟是獲取驗證碼實例--》去除小數情況--》緩存進redis保存,並且設置緩存時間--》返回驗證碼信息給前端

    @ApiOperation("獲取用戶信息")
    @GetMapping(value = "/info")
    public ResponseEntity<Object> getUserInfo() {
        return ResponseEntity.ok(SecurityUtils.getCurrentUser());
    }

    @ApiOperation("獲取驗證碼")
    @AnonymousGetMapping(value = "/code")//支持匿名訪問的get請求
    //ResponseEntity是可以添加HttpStatus狀態碼的HttpEntity的擴展類。被用於RestTemplate和Controller層方法 
    public ResponseEntity<Object> getCode() {
        // 獲取運算的結果
        Captcha captcha = loginProperties.getCaptcha();//得到一個驗證碼實例
        String uuid = properties.getCodeKey() + IdUtil.simpleUUID();//uuid=properties對應的是jwt+獨立的uui
        String captchaValue = captcha.text();
        //當驗證碼類型為 arithmetic時且長度 >= 2 時,captcha.text()的結果有幾率為浮點型,如果二維碼是小數就舍棄掉
        //ordinal():用於獲取某個枚舉對象的位置索引值
        if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) {
            captchaValue = captchaValue.split("\\.")[0];
        }
        // 緩存進redis並且設置過期時間,loginProperties.getLoginCode().getExpiration()是兩分鍾
        redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
        // 驗證碼信息
        Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
            put("img", captcha.toBase64());//jwt用到的編碼方法
            put("uuid", uuid);
        }};
        return ResponseEntity.ok(imgResult);//ok表示返回狀態碼是200
    }

幾個函數分析

getCaptcha()

 

 

 

 

 

其他的登陸功能

前端會傳遞給后端的參數在data里面,上面的url和method是請求

其中的uuid是驗證碼的唯一識別碼(之前后端給前端發送驗證碼的時候同樣也往redis里存了一份,所以后續在后端會從redis緩存中拿出來校對)

 

 后端的接收的對象里包括了這幾個參數

 具體的登陸授權代碼

    @ApiOperation("登錄授權")
    @AnonymousPostMapping(value = "/login")//支持匿名訪問的post請求
    //@Validated注解用於校驗從前端傳遞的參數
    //@RequestBody將json格式的數據轉為java對象,也就是接收前端數據
    public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
        // 密碼解密,使用的私鑰具體在配置文件可以看到
        String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
        // 從redis緩存中拿到驗證碼
        String code = (String) redisUtils.get(authUser.getUuid());
        // 清除驗證碼緩存
        redisUtils.del(authUser.getUuid());
        //判斷驗證碼
        if (StringUtils.isBlank(code)) {
            throw new BadRequestException("驗證碼不存在或已過期");
        }
        if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {//驗證碼不正確
            throw new BadRequestException("驗證碼錯誤");
        }
        //security相關的內容
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = tokenProvider.createToken(authentication);
        //jwtToken規范,不用去服務器端也保存一份token進行校對,只要是沒有過期,就可以使用
        //獲得一個登陸的主題,這里封裝了所有的信息
        final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
        // 保存在線信息,為了看目前有多少人在線
        onlineUserService.save(jwtUserDto, token, request);
        // 返回 token 與 用戶信息
        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user", jwtUserDto);
        }};
        if (loginProperties.isSingleLogin()) {
            //踢掉之前已經登錄的token
            onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
        }
        return ResponseEntity.ok(authInfo);
    }

RsaProperties.privateKey

 

 

 

回顧整個登陸流程:

 

進入登陸頁面,自動獲取驗證碼,每次生成的驗證碼都會不一樣

后端生成驗證碼,通過(uuid,值)的鍵值對放入redis並且設置過期時間為,然后返回uuid,圖片,url給前端

前端通過訪問auth/code獲取后端生成的二維碼

用戶填寫用戶名,密碼,驗證碼,點擊登陸

前端用預設的公匙進行密碼數據加密,發送到后端

后端接收數據后,首先用預設的私匙進行解密,然后從redis中獲取驗證碼,判斷是否正確或者過期,然后清除驗證碼

如果用戶的密碼和驗證碼正確就生成token,並保存在線信息,然后返回用戶信息和token給前端


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM