Procházet zdrojové kódy

管理后台sa token

lyhzzz před 3 roky
rodič
revize
8bcfd3c11f

+ 13 - 0
4dkankan-center-manage/pom.xml

@@ -84,6 +84,19 @@
       <version>1.3.6</version>
     </dependency>
 
+    <!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
+    <dependency>
+      <groupId>cn.dev33</groupId>
+      <artifactId>sa-token-spring-boot-starter</artifactId>
+      <version>1.30.0</version>
+    </dependency>
+    <!-- Sa-Token 整合 jwt -->
+    <dependency>
+      <groupId>cn.dev33</groupId>
+      <artifactId>sa-token-jwt</artifactId>
+      <version>1.30.0</version>
+    </dependency>
+
   </dependencies>
 
   <build>

+ 3 - 0
4dkankan-center-manage/src/main/java/com/fdkankan/manage/ManageApplication.java

@@ -1,5 +1,6 @@
 package com.fdkankan.manage;
 
+import cn.dev33.satoken.SaManager;
 import com.dtflys.forest.springboot.annotation.ForestScan;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
@@ -28,6 +29,8 @@ public class ManageApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ManageApplication.class, args);
+        System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+
     }
 
 }

+ 60 - 0
4dkankan-center-manage/src/main/java/com/fdkankan/manage/config/SaTokenConfigure.java

@@ -0,0 +1,60 @@
+package com.fdkankan.manage.config;
+
+import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+import cn.dev33.satoken.jwt.StpLogicJwtForMixin;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.stp.StpLogic;
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class SaTokenConfigure implements WebMvcConfigurer {
+
+    /**
+     * 注册Sa-Token 的拦截器,打开注解式鉴权功能
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 注册注解拦截器 SaAnnotationInterceptor
+
+        // 注册路由拦截器,自定义认证规则  SaRouteInterceptor
+        registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{
+            // 根据路由划分模块,不同模块不同鉴权
+
+            // 登录认证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
+            SaRouter.match("/**", "/**/login", 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("/goods/**", r -> StpUtil.checkPermission("goods"));
+            SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
+            SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
+            SaRouter.match("/comment/**", r -> StpUtil.checkPermission("comment"));
+
+            // 甚至你可以随意的写一个打印语句
+            SaRouter.match("/**", r -> System.out.println("----啦啦啦----"));
+
+            // 连缀写法
+            SaRouter.match("/**").check(r -> System.out.println("----啦啦啦----"));
+
+        })).addPathPatterns("/**");
+    }
+
+
+    // Sa-Token 整合 jwt
+    //Stateless 无状态模式 纯jwt
+    //Mixin 混入模式 jwt 与 Redis 逻辑混合
+    //Simple 简单模式   Token风格替换
+    @Bean
+    public StpLogic getStpLogicJwt() {
+        return new StpLogicJwtForMixin();
+    }
+}
+

+ 43 - 0
4dkankan-center-manage/src/main/java/com/fdkankan/manage/config/StpInterfaceImpl.java

@@ -0,0 +1,43 @@
+package com.fdkankan.manage.config;
+
+import cn.dev33.satoken.stp.StpInterface;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义权限验证接口扩展
+ */
+@Component
+public class StpInterfaceImpl implements StpInterface {
+
+    /**
+     * 返回一个账号所拥有的权限码集合
+     */
+    @Override
+    public List<String> getPermissionList(Object loginId, String loginType) {
+        // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
+        List<String> list = new ArrayList<String>();
+        list.add("101");
+        list.add("user-add");
+        list.add("user-delete");
+        list.add("user-update");
+        list.add("user-get");
+        list.add("article-get");
+        return list;
+    }
+
+    /**
+     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
+     */
+    @Override
+    public List<String> getRoleList(Object loginId, String loginType) {
+        // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
+        List<String> list = new ArrayList<String>();
+        list.add("admin");
+        list.add("super-admin");
+        return list;
+    }
+
+}

+ 53 - 0
4dkankan-center-manage/src/main/java/com/fdkankan/manage/controller/LoginController.java

@@ -0,0 +1,53 @@
+package com.fdkankan.manage.controller;
+
+import cn.dev33.satoken.stp.SaLoginConfig;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 登录测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/manage/")
+public class LoginController {
+
+    // 测试登录  ----
+    @RequestMapping("login")
+    public SaResult doLogin(String name, String pwd) {
+        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
+        if("cs".equals(name) && "123456".equals(pwd)) {
+            StpUtil.login(10001, SaLoginConfig.setExtra("name","cs"));
+            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
+            return SaResult.data(tokenInfo);
+        }
+        return SaResult.error("登录失败");
+    }
+
+    // 查询登录状态  ----
+    @RequestMapping("isLogin")
+    public SaResult isLogin() {
+        return SaResult.ok("是否登录:" + StpUtil.isLogin());
+    }
+
+    // 查询 Token 信息  ----
+    @RequestMapping("tokenInfo")
+    public SaResult tokenInfo() {
+        String name = (String) StpUtil.getExtra("name");
+        StpUtil.checkPermission("user");
+        return SaResult.data( StpUtil.getTokenInfo());
+    }
+
+    // 测试注销  ----
+    @RequestMapping("logout")
+    public SaResult logout() {
+        StpUtil.logout();
+        return SaResult.ok();
+    }
+
+}
+

+ 13 - 16
4dkankan-center-manage/src/main/java/com/fdkankan/manage/interceptor/VisitLogInterceptor.java

@@ -1,5 +1,6 @@
 package com.fdkankan.manage.interceptor;
 
+import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.servlet.ServletUtil;
 import cn.hutool.http.ContentType;
@@ -7,21 +8,12 @@ import cn.hutool.http.useragent.UserAgent;
 import cn.hutool.http.useragent.UserAgentUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.fdkankan.common.util.JwtUtil;
 import com.fdkankan.manage.bean.MenuBean;
 import com.fdkankan.manage.entity.OperLog;
 import com.fdkankan.redis.constant.RedisKey;
 import com.fdkankan.redis.util.RedisUtil;
-import io.jsonwebtoken.Claims;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Objects;
-import javax.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
@@ -36,6 +28,9 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
 @Component
 @Aspect
 @Slf4j
@@ -85,6 +80,7 @@ public class VisitLogInterceptor {
 		Object result = pjp.proceed();
 
 		//获取用户信息 如果已登录,从token中获取用户信息,如果是登录接口,查询数据库获取用户信息
+
 		Map<String, Object> userInfo = this.getUserInfo(request, uri, result);
 		Long userId = (Long)userInfo.get("userId");
 		String userName = (String)userInfo.get("userName");
@@ -109,15 +105,16 @@ public class VisitLogInterceptor {
 
 	private String getRequestPath(String uri){
 		String hget = redisUtil.hget(RedisKey.MANAGE_MENU, uri);
+		assert StringUtils.isNotBlank(hget);
 		MenuBean menuBean = JSON.parseObject(hget, MenuBean.class);
 		LinkedList<String> menuList = new LinkedList<>();
 		this.getRequestPathHandler(menuList, menuBean);
 		StringBuilder sb = new StringBuilder();
-		menuList.stream().forEach(str->sb.append("->").append(str));
+		menuList.forEach(str->sb.append("->").append(str));
 		return sb.substring(2);
 	}
 
-	private void getRequestPathHandler(LinkedList list, MenuBean menuBean){
+	private void getRequestPathHandler(LinkedList<String> list, MenuBean menuBean){
 		list.addFirst("[" + menuBean.getName() + "]");
 		if(Objects.isNull(menuBean.getParent())){
 			return;
@@ -136,10 +133,10 @@ public class VisitLogInterceptor {
 		}else{
 			token = request.getHeader("token");
 		}
-		Claims claims = JwtUtil.parseJWT(token);
-		Integer userId = (Integer) claims.get("userId");
-		String userName = (String)claims.get("userName");
-		String nickName = (String)claims.get("nickName");
+
+		Integer userId = (Integer)StpUtil.getExtra("userId");
+		String userName = (String)StpUtil.getExtra("userName");
+		String nickName = (String)StpUtil.getExtra("nickName");
 		Map<String, Object> userInfo = new HashMap<>();
 		userInfo.put("userId", Long.valueOf(userId));
 		userInfo.put("userName", userName);

+ 20 - 1
4dkankan-center-manage/src/main/resources/bootstrap.yml

@@ -1,3 +1,22 @@
 spring:
   profiles:
-    active: dev
+    active: dev
+
+# Sa-Token配置
+sa-token:
+  # token名称 (同时也是cookie名称)
+  token-name: satoken
+  # token有效期,单位s 默认30天, -1代表永不过期
+  timeout: -1
+  # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+  activity-timeout: -1
+  # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+  is-concurrent: true
+  # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
+  is-share: false
+  # token风格
+  token-style: uuid
+  jwt-secret-key: 4dkk_manage
+  # 是否输出操作日志
+  is-log: false
+

+ 1 - 10
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java

@@ -16,15 +16,10 @@ import com.fdkankan.common.user.SSOUser;
 import com.fdkankan.common.util.BASE64DecodedMultipartFile;
 import com.fdkankan.common.util.FileUtil;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
-import com.fdkankan.scene.entity.ScenePro;
 import com.fdkankan.scene.entity.SceneUpload;
 import com.fdkankan.scene.mapper.ISceneUploadMapper;
-import com.fdkankan.scene.service.ISceneProService;
 import com.fdkankan.scene.service.ISceneUploadService;
 import com.fdkankan.scene.vo.DeleteFileParamVO;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -33,10 +28,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
 
 /**
  * <p>
@@ -70,7 +62,6 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
     public String uploads(String imgData,String fileName,String blzType,MultipartFile[] files,String sceneCode,Integer type,String token) throws Exception{
         SSOUser ssoUser = ssoLoginHelper.loginCheck(token);
         Long userId = ssoUser == null ? null :ssoUser.getId();
-
         List<MultipartFile> multipartFiles = new ArrayList<>();
         if(StringUtils.isNotBlank(imgData)){
             MultipartFile file = BASE64DecodedMultipartFile.base64ToMultipart(imgData);