1. 程式人生 > 實用技巧 >07 登入介面開發

07 登入介面開發

登入介面開發

登入的邏輯其實很簡答,只需要接受賬號密碼,然後把使用者的id生成jwt,返回給前段,為了後續的jwt的延期,所以我們把jwt放在header上。具體程式碼如下:

  • com.gychen.controller.AccountController
@RestController
public class AccountController {
    @Autowired
    JwtUtils jwtUtils;
    @Autowired
    UserService userService;
    /**
     * 預設賬號密碼:gychen / 111111
     *
     */
    @CrossOrigin
    @PostMapping("/login")
    public Result login(@Validated @RequestBody LoginDto loginDto, HttpServletResponse response) {
        User user = userService.getOne(new QueryWrapper<User>().eq("username", loginDto.getUsername()));
        Assert.notNull(user, "使用者不存在");
        if(!user.getPassword().equals(SecureUtil.md5(loginDto.getPassword()))) {
            return Result.fail("密碼錯誤!");
        }
        String jwt = jwtUtils.generateToken(user.getId());
        response.setHeader("Authorization", jwt);
        response.setHeader("Access-Control-Expose-Headers", "Authorization");
        // 使用者可以另一個介面
        return Result.succ(MapUtil.builder()
                .put("id", user.getId())
                .put("username", user.getUsername())
                .put("avatar", user.getAvatar())
                .put("email", user.getEmail())
                .map()
        );
    }
    
    // 退出
    @GetMapping("/logout")
    @RequiresAuthentication
    public Result logout() {
        SecurityUtils.getSubject().logout();
        return Result.succ(null);
    }
}

  • 在postman軟體裡寫介面請求測試

請求型別為POST,URL為http://localhost:8081/login,依次選擇Body->raw->JSON


{
    "_comment":"postman清求資料",
    "username":"gychen",
    "password":"111111"
}

{
    "_comment":"伺服器返回資料",
    "code": "0",
    "msg": "操作成功",
    "data": {
        "id": 1,
        "avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
        "email": null,
        "username": "gychen"
    }
}

部落格介面開發

我們的骨架已經完成,接下來,我們就可以新增我們的業務介面了,下面我以一個簡單的部落格列表、部落格詳情頁為例子開發:

  • com.gychen.controller.BlogController
package com.gychen.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gychen.common.lang.Result;
import com.gychen.entity.Blog;
import com.gychen.service.BlogService;
import com.gychen.util.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author gychen
 * @since 2020-07-28
 */


@RestController
public class BlogController {
    @Autowired
    BlogService blogService;
    @GetMapping("/blogs")
    public Result blogs(Integer currentPage) {
        if(currentPage == null || currentPage < 1) currentPage = 1;
        Page page = new Page(currentPage, 5);
        IPage pageData = blogService.page(page, new QueryWrapper<Blog>().orderByDesc("created"));
        return Result.succ(pageData);
    }
    @GetMapping("/blog/{id}")
    public Result detail(@PathVariable(name = "id") Long id) {
        Blog blog = blogService.getById(id);
        Assert.notNull(blog, "該部落格已刪除!");
        return Result.succ(blog);
    }

    @RequiresAuthentication    // 此介面必須要通過登入認證才能訪問
    @PostMapping("/blog/edit")
    public Result edit(@Validated @RequestBody Blog blog) {
        System.out.println(blog.toString());
        Blog temp = null;
        if(blog.getId() != null) {
            // 在資料庫中查詢傳入id的部落格存不存在
            temp = blogService.getById(blog.getId());
            // Assert.isTrue(temp.getUserId().longValue() == ShiroUtil.getProfile().getId().longValue(), "沒有許可權編輯");
            Assert.isTrue(temp.getUserId().equals(ShiroUtil.getProfile().getId()), "沒有許可權編輯");
        } else {
            temp = new Blog();
            temp.setUserId(ShiroUtil.getProfile().getId());
            temp.setCreated(LocalDateTime.now());
            temp.setStatus(0);
        }
        // 把blog複製到temp並忽略id、userId、created、status
        BeanUtil.copyProperties(blog, temp, "id", "userId", "created", "status");
        blogService.saveOrUpdate(temp);
        return Result.succ(null);
    }
}


  • 在postman軟體裡寫介面請求測試
  1. 先進行登入請求,登陸成功後在返回資料的請求頭Headers裡找到Authorization的value,複製value值

  2. 新建一個請求,請求型別為POST,URL為http://localhost:8081/blog/edit,在Headers裡新建key:Authorization,value:複製的value值,依次選擇Body->raw->JSON

  3. 測試程式碼

    • {
       "title":"測試標題3333333333",
       "description":"description333333333",
       "content":"content33333333333"
      }
      
    • {
        "title":"測試標題3333333333",
        "description":"description333333333"
      }
      
    • {
       "id":11,
       "title":"測試標題3333333333",
       "description":"description333333333",
       "content":"content33333333333"
      }
      
    • {
       "id":11,
       "title":"修改測試標題3333333333",
       "description":"description333333333",
       "content":"content1111111"
      }
      
  4. 暫時在這裡出現了登入驗證的問題,待解決

  5. 找了大概一個小時,在JwtFilter的onAcessDenied方法裡發現發起請求時,後端根本在Header請求頭裡找不到jwt,後來發現原來是在postman裡把token放Params裡傳給後端了。

  6. 測試結果

    • {
          "code": "0",
          "msg": "操作成功",
          "data": null
      }
      
    • {
          "code": "-1",
          "msg": "內容不能為空",
          "data": null
      }
      
    • {
          "code": "0",
          "msg": "操作成功",
          "data": null
      }
      
    • {
          "code": "0",
          "msg": "操作成功",
          "data": null
      }
      

注意@RequiresAuthentication說明需要登入之後才能訪問的介面,其他需要許可權的介面可以新增shiro的相關注解。 介面比較簡單,我們就不多說了,基本增刪改查而已。注意的是edit方法是需要登入才能操作的受限資源。