sa-token 鑒權框架(springboot集成)


一個輕量級java權限認證框架,讓鑒權變得簡單、優雅(官方文檔描述  哈哈)

一、pom依賴

<dependency>
     <groupId>cn.dev33</groupId>
     <artifactId>sa-token-spring-boot-starter</artifactId>
     <version>1.27.0</version>
</dependency>

二、yml文件配置

# Sa-Token配置
sa-token:
  # token名稱 (同時也是cookie名稱)
  token-name: satoken
  # token有效期,單位s 默認30天, -1代表永不過期
  timeout: 2592000
  # token臨時有效期 (指定時間內無操作就視為token過期) 單位: 秒
  activity-timeout: -1
  # 是否允許同一賬號並發登錄 (為true時允許一起登錄, 為false時新登錄擠掉舊登錄)
  is-concurrent: true
  # 在多人登錄同一賬號時,是否共用一個token (為true時所有登錄共用一個token, 為false時每次登錄新建一個token)
  is-share: false
  # token風格
  token-style: simple-uuid
  # 是否輸出操作日志
  is-log: false
  # 是否打印sa-token標識
  is-print: false

三、實現sa-token權限、角色信息注入

import cn.dev33.satoken.stp.StpInterface;
import com.subgame.dao.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @Author dly
 * @Description 實現satoken權限、角色信息注入
 * @Date 2021/11/6
 * @Param
 * @return
 **/
@Component
public class StpInterfaceImpl implements StpInterface {

    @Autowired
    UserMapper userMapper;

    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        List<String> list = new ArrayList<>();
        list.add("user_get");return list;
    }

    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        String roles = userMapper.selectByPrimaryKey(Integer.valueOf(loginId.toString())).getRoles();
        List<String> list = Arrays.asList(roles.split(","));
        return list;
    }

 

四、注冊攔截器

import cn.dev33.satoken.interceptor.SaRouteInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注冊攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊Sa-Token的路由攔截器
        registry.addInterceptor(new SaRouteInterceptor(
                (req, res, handler)-> {
                    // 根據路由划分模塊,不同模塊不同鑒權
                    SaRouter.match("/user/**", r -> StpUtil.checkPermission("user_get"));
                    SaRouter.match("/manager/**",r -> StpUtil.checkRole("ADMIN"));
                }))
                .addPathPatterns("/**")
                .excludePathPatterns("/manager/adminLogin");
    }
}

五、登錄接口信息識別(根據實際情況自己寫的實現類)

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import com.subgame.base.RespResult;
import com.subgame.base.SubGameException;
import com.subgame.dao.UserMapper;
import com.subgame.model.User;
import com.subgame.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;


    @Override
    public RespResult adminLogin(User user, HttpServletResponse response) {
        User userinfo = userMapper.selectUserByLoginName(user.getLoginName());
        String saltPassword = SaSecureUtil.md5BySalt(user.getPassword(), User.salt);
        if(null == userinfo||!saltPassword.equals(userinfo.getPassword())){
            throw new SubGameException(SubGameException.LoginError,SubGameException.LoginError_Code);
        }
        StpUtil.login(userinfo.getId().toString());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        response.setHeader(tokenInfo.getTokenName(),tokenInfo.getTokenValue());
        RespResult result = new RespResult();
        result.setData(userinfo);
        return result;
    }
}

六、異常處理

全局異常攔截(攔截項目中所有異常)

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.subgame.base.RespResult;
import com.subgame.base.SubGameException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

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

@ControllerAdvice
public class GlobalException {
    // 全局異常攔截(攔截項目中的所有異常)
    @ResponseBody
    @ExceptionHandler
    public RespResult handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 打印堆棧,以供調試
        System.out.println("全局異常---------------");
        e.printStackTrace();
        // 不同異常返回不同狀態碼
        RespResult result = new RespResult();
        if (e instanceof NotLoginException) {    // 如果是未登錄異常
            NotLoginException ee = (NotLoginException) e;
            result.setMessage(ee.getMessage());
            result.setReturnCode("-1");
        }
        else if(e instanceof NotRoleException) {        // 如果是角色異常
            NotRoleException ee = (NotRoleException) e;
            result.setReturnCode("-2");
            result.setMessage(" "+ee.getMessage());
        }
        else if(e instanceof NotPermissionException) {    // 如果是權限異常
            NotPermissionException ee = (NotPermissionException) e;
            result.setReturnCode("-3");
            result.setMessage("無此權限"+ ee.getCode());
        }
        else if(e instanceof DisableLoginException) {    // 如果是被封禁異常
            DisableLoginException ee = (DisableLoginException) e;
            result.setReturnCode("-4");
            result.setMessage("賬號被封禁:" + ee.getDisableTime() + "秒后解封");
        }else if(e instanceof SubGameException){
            SubGameException ee = (SubGameException)e;
            result.setReturnCode(ee.getCode());
            result.setMessage(ee.getMessage());
        }
        else {    // 普通異常, 輸出:500 + 異常信息
            result.setMessage(e.getMessage());
            result.setReturnCode("-999");
        }
        // 返回給前端
        return result;
    }
}

封裝返回對象信息RespResult

import java.io.Serializable;


public class RespResult<T> implements Serializable {

    private static final long serialVersionUID = 5461950698245974856L;

    // 返回代碼
    private String returnCode;

    // 返回代碼描述
    private String message;

    // 返回數據
    private T data;

    public RespResult() {
        this.returnCode = "0";
        this.message = "操作成功";
    }

    public String getReturnCode() {
        return returnCode;
    }

    public void setReturnCode(String returnCode) {
        this.returnCode = returnCode;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "{" + "\"" + "returnCode" + "\"" + ":" + returnCode + ", " + "\"" + "data" + "\"" + ":" + data + "}";
    }
}
View Code

自定義異常類 SubGameException

import org.apache.ibatis.annotations.Case;

public class SubGameException extends RuntimeException{

    public static final String LoginError = "用戶名或密碼錯誤";
    public static final String LoginError_Code = "-5";
    public String code;


    public String getCode() {
        return code;
    }

    public SubGameException(String message,String code){
        super(message);
        this.code = code;
    }

    public SubGameException(String message, Throwable cause) {
        super(message, cause);
    }

    public SubGameException(Throwable cause) {
        super(cause);
    }

}
View Code

 

根據api搭建大概簡單的鑒權框架

更多詳細其他配置信息見官網:https://sa-token.dev33.cn/


免責聲明!

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



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