使用sa-token实现权限控制

This commit is contained in:
LittleBoy 2022-05-17 10:39:07 +08:00
parent b1ca1ace25
commit aa94cb3307
11 changed files with 140 additions and 14 deletions

View File

@ -86,11 +86,26 @@
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!-- shiro的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.9.0</version>
</dependency>
<!-- sa-token依赖 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.30.0</version>
</dependency>
<!-- Sa-Token 整合 Redis 使用jackson序列化方式 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.30.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>

View File

@ -0,0 +1,53 @@
package xyz.longicorn.driver.config;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import xyz.longicorn.driver.dto.ApiResult;
// 主要处理sa-token的拦截和跨域问题
@Configuration
public class SaTokenConfig {
@Bean
public SaServletFilter getSaServletFilter() {
return new SaServletFilter()
.addExclude(
"/druid/**",
"/api/user/login",
"/api/user/reg",
"/api/user/forget",
"/api/user/reset",
"/swagger**",
"/swagger-resources/**",
"/v2/api-docs",
"/picture/**"
)
.addExclude("/**")
.setError(new SaFilterErrorStrategy() {
@Override
public Object run(Throwable e) {
return ApiResult.error(401, e.getMessage());
}
})
.setBeforeAuth(obj -> {
// ---------- 设置跨域响应头 ----------
SaHolder.getResponse()
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "*")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*");
// 如果是预检请求则立即返回到前端
SaRouter.match(SaHttpMethod.OPTIONS)
.free(r -> System.out.println("--------OPTIONS预检请求不做处理"))
.back();
});
}
}

View File

@ -1,5 +1,11 @@
package xyz.longicorn.driver.config;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.interceptor.SaRouteInterceptor;
import cn.dev33.satoken.router.SaRouteFunction;
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.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@ -11,6 +17,42 @@ public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 简单的登录拦截
// registry.addInterceptor(new SaRouteInterceptor())
// .addPathPatterns("/**") // 要拦截的路由地址
// .excludePathPatterns(
// "/druid/**",
// "/api/user/login",
// "/api/user/reg",
// "/api/user/forget",
// "/api/user/reset",
// "/swagger**",
// "/swagger-resources/**",
// "/v2/api-docs",
// "/picture/**"
// );
// 复杂的权限登录拦截
// registry.addInterceptor(new SaRouteInterceptor(new SaRouteFunction() {
// @Override
// public void run(SaRequest req, SaResponse res, Object handler) {
// // 登录认证 -- 拦截所有路由并排除/user/doLogin 用于开放登录
// SaRouter.match("/**", "/user/doLogin", r -> StpUtil.checkLogin());
//
// // 角色认证 -- 拦截以 admin 开头的路由必须具备 admin 角色或者 super-admin 角色才可以通过认证
// SaRouter.match("/admin/**", r -> StpUtil.checkRoleOr("admin", "super-admin"));
//
// // 权限认证 -- 不同模块认证不同权限
// SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
// SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
//
// // 甚至你可以随意的写一个打印语句
// SaRouter.match("/**", r -> System.out.println("----啦啦啦----"));
//
// // 连缀写法
// SaRouter.match("/**").check(r -> System.out.println("----啦啦啦----"));
// }
// }))
// .addPathPatterns("/**");
}
@Override

View File

@ -1,5 +1,6 @@
package xyz.longicorn.driver.controller;
import cn.dev33.satoken.stp.StpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@ -9,6 +10,7 @@ import xyz.longicorn.driver.dto.ApiResult;
import xyz.longicorn.driver.dto.FileItem;
import xyz.longicorn.driver.dto.FolderDto;
import xyz.longicorn.driver.pojo.FolderInfo;
import xyz.longicorn.driver.pojo.UserInfo;
import xyz.longicorn.driver.service.FolderService;
import javax.annotation.Resource;
@ -26,8 +28,10 @@ public class FolderController {
//接口文档的名称
@ApiOperation(value = "查询目录信息", notes = "查询相应目录下的所有文件(夹)信息", httpMethod = "GET")
public ApiResult listFolder(@RequestParam(required = false, defaultValue = "/") String folderPath) {
UserInfo info = StpUtil.getSession().get("user", new UserInfo().setId(0));
return ApiResult.success(
folderService.listFolder(1, folderPath)
folderService.listFolder(StpUtil.getLoginId(0), folderPath)
);
}

View File

@ -27,7 +27,7 @@ public class UserController {
@SneakyThrows
@PostMapping("/login")
public ApiResult login(@Validated @RequestBody LoginModel model) {
Thread.sleep(5);
Thread.sleep(3);
final LoginUser user = userService.login(model.getUsername(), model.getPassword());
return ApiResult.success(user);

View File

@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@ -15,7 +16,7 @@ import java.util.Date;
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class UserInfo {
public class UserInfo implements Serializable {
private Integer id;
private String nickname;

View File

@ -1,5 +1,6 @@
package xyz.longicorn.driver.service;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -44,9 +45,12 @@ public class UserService extends ServiceImpl<UserInfoMapper, UserInfo> {
// 将登录数据保存到redis 用户后续判断
LoginUser user = new LoginUser();
user.setAccount(account);
StpUtil.login(userInfo.getId()); // 使用用户编号在sa-token 完成登录
StpUtil.getSession().set("user",userInfo);
// 生成接口需要的token
user.setToken(IdUtil.fastSimpleUUID()); // 可以使用jwt生成token
loginUserDao.save(user); // 保存用户登录信息到redis
// user.setToken(IdUtil.fastSimpleUUID()); // 可以使用jwt生成token
user.setToken(StpUtil.getTokenValue());
// loginUserDao.save(user); // 保存用户登录信息到redis
user.setUserInfo(userInfo);
return user;
}

View File

@ -15,7 +15,6 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Resource
private LoginUserDao loginUserDao;

View File

@ -71,3 +71,5 @@ mybatis-plus:
# 实体类所在的包
type-aliases-package: xyz.longicorn.driver.pojo
type-enums-package: xyz.longicorn.driver.pojo.enums
sa-token:
token-name: Authorization

View File

@ -1,7 +1,7 @@
<template>
<span style="display:inline-block">
<el-image v-if="type == 'picture'" ref="img"
:src="currentSrc" :previewSrcList="[currentPreview]"
:src="currentSrc"
:initial-index="4" fit="cover" :hide-on-click-modal="true"
/>
<img v-else class="file-icon" :src="currentSrc"/>

View File

@ -6,10 +6,10 @@
<div v-else>
<el-breadcrumb separator="/" style="line-height: 30px">
<el-breadcrumb-item>
<a href="#?path=/">全部文件</a>
<router-link to="?path=/">全部文件</router-link>
</el-breadcrumb-item>
<el-breadcrumb-item v-for="p in currentPathList" :key="p.path">
<a v-if="p.path" :href="'#?path=' + p.path">{{ p.name }}</a>
<router-link v-if="p.path" :to="'?path=' + p.path">{{ p.name }}</router-link>
<span v-else>{{ p.name }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
@ -202,6 +202,12 @@ export default {
}
}
},
watch:{
'$route'(){
// console.log(this.$route)
this.handleHashChange();
}
},
computed: {
currentPathList() {
if (this.currentPath == '/') return []
@ -220,12 +226,12 @@ export default {
components: {FileBlockItem, FileIcon, ArrowDown, Grid, FolderAdd},
mounted() {
console.log('记载所有的文件')
window.addEventListener('popstate',()=>console.log(location.href))
window.addEventListener('hashchange', this.handleHashChange) //
// window.addEventListener('popstate',()=>console.log(location.href))
// window.addEventListener('hashchange', this.handleHashChange) //
this.handleHashChange();
},
unmounted() {
window.removeEventListener('hashchange', this.handleHashChange); //
// window.removeEventListener('hashchange', this.handleHashChange); //
},
methods: {
//
@ -242,8 +248,8 @@ export default {
},
//
getCurrentPath() {
const hash = location.hash;
const params = qs.parse(hash.substr(2))
const query = this.$route.query;
const params = qs.parse(query)
return params.path || '/';
},
//