Initial commit

This commit is contained in:
yovinchen 2023-06-10 23:57:03 +08:00
parent d6b795311f
commit 57e9cababa
31 changed files with 915 additions and 37 deletions

12
.idea/dataSources.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="@localhost" uuid="25fdbc9a-4257-49cd-83d7-9dab48532057">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@ -5,6 +5,7 @@
<file url="file://$PROJECT_DIR$/common/common-util/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/service-util/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/service-util/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/spring-security/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/model/src/main/java" charset="UTF-8" />

7
.idea/sqldialects.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/service-oa/src/main/java/com/atguigu/auth/mapper/xml/SysMenuMapper.xml" dialect="GenericSQL" />
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

View File

@ -13,7 +13,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided </scope>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
@ -27,5 +27,11 @@
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,102 @@
package com.atguigu.common.jwt;
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;
import java.util.Date;
/**
* ClassName: JitHelper
* Package: com.atguigu.common.jwt
* JWT工具类
*
* @author yovinchen
* @Create 2023/6/10 16:12
*/
public class JwtHelper {
private static final long tokenExpiration = 365L * 24 * 60 * 60 * 1000;
private static final String tokenSignKey = "123456";
/**
* 根据用户 id 和用户名称 生成token的字符串
*
* @param userId
* @param username
* @return
*/
public static String createToken(Long userId, String username) {
String token = Jwts.builder()
//分类
.setSubject("AUTH-USER")
//设置Token有效时长
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
//设置主体部分
.claim("userId", userId)
.claim("username", username)
//签名部分
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
.compressWith(CompressionCodecs.GZIP)
.compact();
return token;
}
/**
* 从生成的Token中获取id
*
* @param token
* @return
*/
public static Long getUserId(String token) {
try {
if (StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Integer userId = (Integer) claims.get("userId");
return userId.longValue();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 从Token中获取用户名称
*
* @param token
* @return
*/
public static String getUsername(String token) {
try {
if (StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String) claims.get("username");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
String token = JwtHelper.createToken(1L, "admin");
System.out.println(token);
String username = JwtHelper.getUsername(token);
Long userId = JwtHelper.getUserId(token);
System.out.println("username = " + username);
System.out.println("userId = " + userId);
}
}

View File

@ -18,7 +18,7 @@ public enum ResultCodeEnum {
FAIL(201, "失败"),
SERVICE_ERROR(2012, "服务异常"),
DATA_ERROR(204, "数据异常"),
LOGIN_ERROR(205, "认证失败"),
LOGIN_AUTH(208, "未登陆"),
PERMISSION(209, "没有权限");

View File

@ -0,0 +1,33 @@
package com.atguigu.common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class MD5 {
public static String encrypt(String strSrc) {
try {
char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f'};
byte[] bytes = strSrc.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (byte b : bytes) {
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错+" + e);
}
}
public static void main(String[] args) {
System.out.println(MD5.encrypt("111111"));
}
}

View File

@ -0,0 +1,30 @@
package com.atguigu.common.utils;
import com.atguigu.common.result.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* ClassName: ResponseUtil
* Package: com.atguigu.common.utils
*
* @author yovinchen
* @Create 2023/6/10 23:42
*/
public class ResponseUtil {
public static void out(HttpServletResponse response, Result r) {
ObjectMapper mapper = new ObjectMapper();
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
try {
mapper.writeValue(response.getWriter(), r);
} catch (IOException e) {
e.printStackTrace();
}
}
}

38
common/spring-security/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>guigu-oa-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>spring-security</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring Security依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,19 @@
package com.atguigu.security.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* ClassName: WebSecurityConfig
* Package: com.atguigu.security.config
*
* @author yovinchen
* @Create 2023/6/10 22:47
*/
@Configuration
//@EnableWebSecurity是开启SpringSecurity的默认行为
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

View File

@ -0,0 +1,25 @@
package com.atguigu.security.custom;
import com.atguigu.common.utils.MD5;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
/**
* ClassName: CustomMd5PasswordEncoder
* Package: com.atguigu.security.custom
* 密码处理
*
* @author yovinchen
* @Create 2023/6/10 23:23
*/
@Component
public class CustomMd5PasswordEncoder implements PasswordEncoder {
public String encode(CharSequence rawPassword) {
return MD5.encrypt(rawPassword.toString());
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));
}
}

View File

@ -0,0 +1,36 @@
package com.atguigu.security.custom;
import com.atguigu.model.system.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
/**
* ClassName: CustomUser
* Package: com.atguigu.security.custom
*
* @author yovinchen
* @Create 2023/6/10 23:24
*/
public class CustomUser extends User {
/**
* 我们自己的用户实体对象要调取用户信息时直接获取这个实体对象这里我就不写get/set方法了
*/
private SysUser sysUser;
public CustomUser(SysUser sysUser, Collection<? extends GrantedAuthority> authorities) {
super(sysUser.getUsername(), sysUser.getPassword(), authorities);
this.sysUser = sysUser;
}
public SysUser getSysUser() {
return sysUser;
}
public void setSysUser(SysUser sysUser) {
this.sysUser = sysUser;
}
}

View File

@ -0,0 +1,23 @@
package com.atguigu.security.custom;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
* ClassName: UserDetailsService
* Package: com.atguigu.security.custom
*
* @author yovinchen
* @Create 2023/6/10 23:28
*/
public interface UserDetailsService {
/**
* 根据用户名获取用户对象获取不到直接抛异常
*
* @param username
* @return
* @throws UsernameNotFoundException
*/
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

View File

@ -0,0 +1,64 @@
package com.atguigu.security.filter;
import com.atguigu.common.jwt.JwtHelper;
import com.atguigu.common.result.Result;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.common.utils.ResponseUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
/**
* ClassName: TokenAuthenticationFilter
* Package: com.atguigu.security.custom.filter
* 认证解析token过滤器
*
* @author yovinchen
* @Create 2023/6/10 23:45
*/
public class TokenAuthenticationFilter extends OncePerRequestFilter {
public TokenAuthenticationFilter() {
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("uri:" + request.getRequestURI());
//如果是登录接口直接放行
if ("/admin/system/index/login".equals(request.getRequestURI())) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
if (null != authentication) {
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
} else {
ResponseUtil.out(response, Result.build(null, ResultCodeEnum.LOGIN_ERROR));
}
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// token置于header里
String token = request.getHeader("token");
logger.info("token:" + token);
if (!StringUtils.isEmpty(token)) {
String useruame = JwtHelper.getUsername(token);
logger.info("useruame:" + useruame);
if (!StringUtils.isEmpty(useruame)) {
return new UsernamePasswordAuthenticationToken(useruame, null, Collections.emptyList());
}
}
return null;
}
}

View File

@ -0,0 +1,90 @@
package com.atguigu.security.filter;
import com.atguigu.common.jwt.JwtHelper;
import com.atguigu.common.result.Result;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.common.utils.ResponseUtil;
import com.atguigu.security.custom.CustomUser;
import com.atguigu.vo.system.LoginVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* ClassName: TokenLoginFilter
* Package: com.atguigu.security.custom.filter
* 登录过滤器继承UsernamePasswordAuthenticationFilter对用户名密码进行登录校验
*
* @author yovinchen
* @Create 2023/6/10 23:37
*/
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
// 构造方法
public TokenLoginFilter(AuthenticationManager authenticationManager) {
this.setAuthenticationManager(authenticationManager);
this.setPostOnly(false);
//指定登录接口及提交方式可以指定任意路径
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/system/index/login", "POST"));
}
// 登录认证过程
// 获取输入的用户名和密码调用方法认证
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
try {
// 获取用户信息
LoginVo loginVo = new ObjectMapper().readValue(req.getInputStream(), LoginVo.class);
//封装对象
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
//调用方法
return this.getAuthenticationManager().authenticate(authenticationToken);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 认证成功调用的方法
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {
// 获取当前用户
CustomUser customUser = (CustomUser) auth.getPrincipal();
// 生成token
String token = JwtHelper.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
// 返回
Map<String, Object> map = new HashMap<>();
map.put("token", token);
ResponseUtil.out(response, Result.ok(map));
}
// 认证失败调用的方法
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
if (e.getCause() instanceof RuntimeException) {
ResponseUtil.out(response, Result.build(null, ResultCodeEnum.DATA_ERROR));
} else {
ResponseUtil.out(response, Result.build(null, ResultCodeEnum.LOGIN_AUTH));
}
}
}

View File

@ -2,6 +2,7 @@ package com.atguigu.model.system;
import com.atguigu.model.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -11,7 +12,7 @@ import lombok.Data;
@ApiModel(description = "角色菜单")
@TableName("sys_role_menu")
public class SysRoleMenu extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "角色id")

View File

@ -17,6 +17,7 @@
<module>common</module>
<module>model</module>
<module>service-oa</module>
<module>common/spring-security</module>
</modules>
<properties>

View File

@ -20,6 +20,11 @@
<artifactId>service-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>spring-security</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -27,7 +32,7 @@
<scope>test</scope>
</dependency>
<!-- 代码生成器-->
<!-- 代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
@ -49,5 +54,25 @@
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>

View File

@ -1,23 +1,33 @@
package com.atguigu.auth.controller;
import com.atguigu.auth.service.SysMenuService;
import com.atguigu.auth.service.SysUserService;
import com.atguigu.common.execption.GuiguException;
import com.atguigu.common.jwt.JwtHelper;
import com.atguigu.common.result.Result;
import com.atguigu.common.utils.MD5;
import com.atguigu.model.system.SysUser;
import com.atguigu.vo.system.LoginVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* ClassName: IndexController
* Package: com.atguigu.auth.controller
* 后台登录登出
*
* @author yovinchen
* @Create 2023/6/8 20:32
* 后台登录登出
*/
@Api(tags = "后台登录管理")
@RestController
@ -25,6 +35,11 @@ import java.util.Map;
public class IndexController {
@Autowired
private SysMenuService sysMenuService;
@Autowired
private SysUserService sysUserService;
/**
* 登录
*
@ -32,9 +47,29 @@ public class IndexController {
*/
@ApiOperation("登陆")
@PostMapping("login")
public Result login() {
public Result login(@RequestBody LoginVo loginVo) {
// Map<String, Object> map = new HashMap<>();
// map.put("token", "admin");
// return Result.ok(map);
//获取输入用户名和密码,根据用户名查询数据库
SysUser sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, loginVo.getUsername()));
//用户信息是否存在
if (sysUser == null) {
throw new GuiguException(201, "用户不存在");
}
//判断密码
if (!Objects.equals(sysUser.getPassword(), MD5.encrypt(loginVo.getPassword()))) {
throw new GuiguException(201, "密码错误");
}
//判断用户是否被禁用
if (sysUser.getStatus() == 0) {
throw new GuiguException(201, "用户已经被禁用,请联系管理员");
}
//利用 JWT 根据用户的id和用户名生成Token
Map<String, Object> map = new HashMap<>();
map.put("token", "admin");
map.put("token", JwtHelper.createToken(sysUser.getId(), sysUser.getUsername()));
//返回
return Result.ok(map);
}
@ -45,11 +80,33 @@ public class IndexController {
*/
@ApiOperation("获取用户信息")
@GetMapping("info")
public Result info() {
public Result info(HttpServletRequest request) {
//获取请求头中Token字符串解密出用户信息
String token = request.getHeader("token");
//根据用户信息查询数据库获取用户信息
Long userId =JwtHelper.getUserId(token);
SysUser sysUser = sysUserService.getById(userId);
//根据用户id获取用户可以操作菜单列表
//查询数据库动态构建路由结构
List<RouterVo> routerList = sysMenuService.findUserMenuListByUserId(userId);
//根据用户id获取用户可以操作按钮列表
List<String> permsList = sysMenuService.findUserPermsByUserId(userId);
//返回相应数据
Map<String, Object> map = new HashMap<>();
map.put("roles", "[admin]");
map.put("name", "admin");
map.put("name", sysUser.getName());
map.put("avatar", "https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
// 返回用户可以操作的菜单
map.put("routers", routerList);
// 返回用户可以操作的按钮
map.put("buttons", permsList);
return Result.ok(map);
}

View File

@ -34,9 +34,9 @@ public class SysMenuController {
* @return
*/
@ApiOperation(value = "根据角色获取菜单")
@GetMapping("toAssign/{roleId}")
@GetMapping("/toAssign/{roleId}")
public Result toAssign(@PathVariable Long roleId) {
List<SysMenu> list = sysMenuService.findSysMenuByRoleId(roleId);
List<SysMenu> list = sysMenuService.findMenuByRoleId(roleId);
return Result.ok(list);
}

View File

@ -3,6 +3,7 @@ package com.atguigu.auth.controller;
import com.atguigu.auth.service.SysUserService;
import com.atguigu.common.result.Result;
import com.atguigu.common.utils.MD5;
import com.atguigu.model.system.SysUser;
import com.atguigu.vo.system.SysUserQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -107,6 +108,8 @@ public class SysUserController {
@ApiOperation(value = "保存用户")
@PostMapping("save")
public Result save(@RequestBody SysUser user) {
//对密码进行MD5加密只能加密不能解密
user.setPassword(MD5.encrypt(user.getPassword()));
sysUserService.save(user);
return Result.ok();
}

View File

@ -2,6 +2,9 @@ package com.atguigu.auth.mapper;
import com.atguigu.model.system.SysMenu;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
@ -13,4 +16,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface SysMenuMapper extends BaseMapper<SysMenu> {
/**
* 多表关联查询用户角色关系表角色菜单关系表菜单表
*
* @param userId
* @return
*/
List<SysMenu> findUserMenuListByUserId(@Param("userId") Long userId);
}

View File

@ -1,5 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.auth.mapper.SysMenuMapper">
<resultMap id="sysMenuMap"
type="com.atguigu.model.system.SysMenu" autoMapping="true">
</resultMap>
<select id="findUserMenuListByUserId" resultMap="sysMenuMap">
select distinct m.id,
m.parent_id,
m.name,
m.type,
m.path,
m.component,
m.perms,
m.icon,
m.sort_value,
m.status,
m.create_time,
m.update_time,
m.is_deleted
from sys_menu m
inner join sys_role_menu rm on rm.menu_id = m.id
inner join sys_user_role ur on ur.role_id = rm.role_id
where ur.user_id = #{userId}
and m.status = 1
and rm.is_deleted = 0
and ur.is_deleted = 0
and m.is_deleted = 0
</select>
</mapper>

View File

@ -2,6 +2,7 @@ package com.atguigu.auth.service;
import com.atguigu.model.system.SysMenu;
import com.atguigu.vo.system.AssginMenuVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -36,7 +37,7 @@ public interface SysMenuService extends IService<SysMenu> {
* @param roleId
* @return
*/
List<SysMenu> findSysMenuByRoleId(Long roleId);
List<SysMenu> findMenuByRoleId(Long roleId);
/**
* 给角色分配权限
@ -44,4 +45,20 @@ public interface SysMenuService extends IService<SysMenu> {
* @param assignMenuVo
*/
void doAssign(AssginMenuVo assignMenuVo);
/**
* 获取用户操作菜单
*
* @param userId
* @return
*/
List<RouterVo> findUserMenuListByUserId(Long userId);
/**
* 获取用户操作按钮
*
* @param userId
* @return
*/
List<String> findUserPermsByUserId(Long userId);
}

View File

@ -15,10 +15,18 @@ import java.util.Map;
*/
public interface SysRoleService extends IService<SysRole> {
//查询所有角色和当前用户所属角色
/**
* 查询所有角色和当前用户所属角色
*
* @param userId
* @return
*/
Map<String, Object> findRoleByUserId(Long userId);
//为用户分配角色
/**
* 为用户分配角色
*
* @param assginRoleVo
*/
void doAssign(AssginRoleVo assginRoleVo);
}

View File

@ -20,4 +20,12 @@ public interface SysUserService extends IService<SysUser> {
* @param status
*/
void updateStatus(Long id, Integer status);
/**
* 根据用户名进行查询
*
* @param username
* @return
*/
SysUser getByUsername(String username);
}

View File

@ -1,18 +1,23 @@
package com.atguigu.auth.service.impl;
import com.atguigu.auth.mapper.SysMenuMapper;
import com.atguigu.auth.mapper.SysRoleMenuMapper;
import com.atguigu.auth.service.SysMenuService;
import com.atguigu.auth.service.SysRoleMenuService;
import com.atguigu.auth.utils.MenuHelper;
import com.atguigu.common.execption.GuiguException;
import com.atguigu.model.system.SysMenu;
import com.atguigu.model.system.SysRoleMenu;
import com.atguigu.vo.system.AssginMenuVo;
import com.atguigu.vo.system.MetaVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -27,8 +32,8 @@ import java.util.stream.Collectors;
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
private SysRoleMenuMapper sysRoleMenuMapper;
@Autowired
private SysRoleMenuService sysRoleMenuService;
/**
* 菜单列表
@ -71,24 +76,36 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
* @return
*/
@Override
public List<SysMenu> findSysMenuByRoleId(Long roleId) {
//查询所有菜单
List<SysMenu> allSysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
public List<SysMenu> findMenuByRoleId(Long roleId) {
//1 查询所有菜单- 添加条件 status=1
//在角色菜单关系表中根据角色id获取角色对应的所有菜单id
List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
//根据获取菜单id获取对应菜单对象
// LambdaQueryWrapper<SysMenu> wrapperSysMenu = new LambdaQueryWrapper<>();
// wrapperSysMenu.eq(SysMenu::getStatus, 1);
// List<SysMenu> allSysMenuList = baseMapper.selectList(wrapperSysMenu);
List<SysMenu> allSysMenuList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
//2 根据角色id roleId查询 角色菜单关系表里面 角色id对应所有的菜单id
// LambdaQueryWrapper<SysRoleMenu> wrapperSysRoleMenu = new LambdaQueryWrapper<>();
// wrapperSysRoleMenu.eq(SysRoleMenu::getRoleId, roleId);
// List<SysRoleMenu> sysRoleMenuList = sysRoleMenuService.list(wrapperSysRoleMenu);
List<SysRoleMenu> sysRoleMenuList = sysRoleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
//3 根据获取菜单id获取对应菜单对象
List<Long> menuIdList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
//根据菜单id和所有菜单集合中id比较相同则封装
allSysMenuList.forEach(permission -> {
if (menuIdList.contains(permission.getId())) {
permission.setSelect(true);
//3.1 拿着菜单id 和所有菜单集合里面id进行比较如果相同封装
allSysMenuList.forEach(item -> {
if (menuIdList.contains(item.getId())) {
item.setSelect(true);
} else {
permission.setSelect(false);
item.setSelect(false);
}
});
//返回规定格式的菜单列表
return MenuHelper.buildTree(allSysMenuList);
//4 返回规定树形显示格式菜单列表
List<SysMenu> sysMenuList = MenuHelper.buildTree(allSysMenuList);
return sysMenuList;
}
/**
@ -99,7 +116,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
@Override
public void doAssign(AssginMenuVo assignMenuVo) {
//根据角色id 删除菜单角色表 分配数据
sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, assignMenuVo.getRoleId()));
sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, assignMenuVo.getRoleId()));
//从参数里面获取角色新分配菜单id列表
//进行遍历把每个id 数据添加菜单角色表
for (Long menuId : assignMenuVo.getMenuIdList()) {
@ -107,8 +124,132 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
SysRoleMenu rolePermission = new SysRoleMenu();
rolePermission.setRoleId(assignMenuVo.getRoleId());
rolePermission.setMenuId(menuId);
sysRoleMenuMapper.insert(rolePermission);
sysRoleMenuService.save(rolePermission);
}
}
/**
* 获取用户操作菜单
*
* @param userId
* @return
*/
@Override
public List<RouterVo> findUserMenuListByUserId(Long userId) {
List<SysMenu> sysMenusList = null;
// 1判断当前用户是否是管理员 userId=1 是管理员
// 1.1 如果是管理员查询所有菜单列表
if (userId == 1) {
// 查询所有菜单列表
sysMenusList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1).orderByAsc(SysMenu::getSortValue));
} else {
// 1.2如果不是管理员根据 userId 查询可以操作菜单列表
// 多表关联查询:sys_rolesys_role_menusys_menu
sysMenusList = baseMapper.findUserMenuListByUserId(userId);
}
// 2把查询出来的数据列表 构建成框架要求的路由结构
// 先构建树形结构
List<SysMenu> sysMenuTreeList = MenuHelper.buildTree(sysMenusList);
// 构建框架要求的路由结构
return this.buildRouter(sysMenuTreeList);
}
/**
* 构建框架要求的路由结构
*
* @param menus
* @return
*/
private List<RouterVo> buildRouter(List<SysMenu> menus) {
// 创建 list 集合存值最终数据
List<RouterVo> routers = new ArrayList<>();
// menus 遍历
for (SysMenu menu : menus) {
RouterVo router = new RouterVo();
router.setHidden(false);
router.setAlwaysShow(false);
router.setPath(getRouterPath(menu));
router.setComponent(menu.getComponent());
router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
// 下一层数据
List<SysMenu> children = menu.getChildren();
if (menu.getType() == 1) {
// 加载隐藏路由
List<SysMenu> hiddenMenuList = children.stream()
.filter(item -> !StringUtils.isEmpty(item.getComponent()))
.collect(Collectors.toList());
for (SysMenu hiddenMenu : hiddenMenuList) {
RouterVo hiddenRouter = new RouterVo();
hiddenRouter.setHidden(true);
hiddenRouter.setAlwaysShow(false);
hiddenRouter.setPath(getRouterPath(hiddenMenu));
hiddenRouter.setComponent(hiddenMenu.getComponent());
hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));
routers.add(hiddenRouter);
}
} else {
if (!CollectionUtils.isEmpty(children)) {
if (children.size() > 0) {
router.setAlwaysShow(true);
}
// 递归
router.setChildren(buildRouter(children));
}
}
routers.add(router);
}
return routers;
}
/**
* 获取路由地址
*
* @param menu 菜单信息
* @return 路由地址
*/
public String getRouterPath(SysMenu menu) {
String routerPath = "/" + menu.getPath();
if (menu.getParentId().intValue() != 0) {
routerPath = menu.getPath();
}
return routerPath;
}
/**
* 获取用户操作按钮
*
* @param userId
* @return
*/
@Override
public List<String> findUserPermsByUserId(Long userId) {
// 1判断是否是管理员如果是管理员查询所有按钮列表
List<SysMenu> sysMenusList = null;
if (userId == 1) {
// 查询所有菜单列表
sysMenusList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
} else {
// 2如果不是管理员根据userId查询可以操作按钮列表
// 多表关联查询:sys_rolesys_role_menusys_menu
sysMenusList = baseMapper.findUserMenuListByUserId(userId);
}
// 3从查询出来的数据里面获取可以操作按钮值的List集合返回
// List<String> resultList = new ArrayList<>();
// for (SysMenu item : sysMenusList) {
// if (item.getType() == 2) {
// resultList.add(item.getPerms());
// }
// }
// return resultList;
return sysMenusList.stream()
.filter(item -> item.getType() == 2)
.map(SysMenu::getPerms)
.collect(Collectors.toList());
}
}

View File

@ -3,6 +3,7 @@ package com.atguigu.auth.service.impl;
import com.atguigu.auth.mapper.SysUserMapper;
import com.atguigu.auth.service.SysUserService;
import com.atguigu.model.system.SysUser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -37,4 +38,15 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
baseMapper.updateById(sysUser);
}
/**
* 根据用户名进行查询
*
* @param username
* @return
*/
@Override
public SysUser getByUsername(String username) {
return baseMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
}
}

View File

@ -0,0 +1,39 @@
package com.atguigu.auth.service.impl;
import com.atguigu.auth.service.SysUserService;
import com.atguigu.model.system.SysUser;
import com.atguigu.security.custom.CustomUser;
import com.atguigu.security.custom.UserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.Collections;
/**
* ClassName: UserDetailsServiceImpl
* Package: com.atguigu.auth.service.impl
*
* @author yovinchen
* @Create 2023/6/10 23:31
*/
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser sysUser = sysUserService.getByUsername(username);
if(null == sysUser) {
throw new UsernameNotFoundException("用户名不存在!");
}
if(sysUser.getStatus() == 0) {
throw new RuntimeException("账号已停用");
}
return new CustomUser(sysUser, Collections.emptyList());
}
}

View File

@ -4,6 +4,8 @@ mybatis-plus:
configuration:
# 查看日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:com/atguigu/auth/mapper/xml/*.xml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource