- 添加JwtConfig
- 添加Jwt工具类
- 添加Role RolePermission RoleUser实体类
- 修改User实体类,去除salt字段
- 添加自定义JwtUser类
This commit is contained in:
yulinling 2025-06-11 23:34:28 +08:00
parent 6160c48c7b
commit ee0109c876
12 changed files with 451 additions and 7 deletions

16
pom.xml
View File

@ -111,6 +111,22 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<!-- JWT 工具jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,31 @@
package asia.yulinling.workflow.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* <p>
* JWT配置类
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@ConfigurationProperties(prefix = "jwt.config")
@Data
public class JwtConfig {
/**
* jwt 加密 key默认值kw.
*/
private String key = "kw";
/**
* jwt 过期时间默认值600000 {@code 10 分钟}.
*/
private Long ttl = 600000L;
/**
* 开启 记住我 之后 jwt 过期时间默认值 604800000 {@code 7 }
*/
private Long remember = 604800000L;
}

View File

@ -5,6 +5,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
@Configuration @Configuration
@ -21,4 +23,12 @@ public class SecurityConfig {
.rememberMe(Customizer.withDefaults()); .rememberMe(Customizer.withDefaults());
return http.build(); return http.build();
} }
/**
* 使用默认密码加密
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
} }

View File

@ -0,0 +1,60 @@
package asia.yulinling.workflow.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 权限
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("`wk_permission`")
public class Permission {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 权限名
*/
private String name;
/**
* 类型为页面时,代表前端路由地址,类型为按钮时,代表后端接口地址
*/
private String url;
/**
* 权限类型,页面-1,按钮-2
*/
private Integer type;
/**
* 权限表达式
*/
private String permission;
/**
* 排序
*/
private Integer sort;
/**
* 父级Id
*/
private Long parentId;
}

View File

@ -0,0 +1,54 @@
package asia.yulinling.workflow.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* <p>
* 角色
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("wk_role")
public class Role {
/**
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 角色名
*/
private String name;
/**
* 描述
*/
private String description;
/**
* 创建时间
*/
@TableField("create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField("update_time")
private Date updateTime;
}

View File

@ -0,0 +1,25 @@
package asia.yulinling.workflow.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* <p>
* 角色权限
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@Data
@TableName("wk_role_permission")
public class RolePermission {
/**
* 角色id
*/
private Long roleId;
/**
* 权限id
*/
private Long permissionId;
}

View File

@ -0,0 +1,25 @@
package asia.yulinling.workflow.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* <p>
* 角色用户
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@Data
@TableName("wk_role_user")
public class RoleUser {
/**
* 权限id
*/
private Long roleId;
/**
* 用户id
*/
private Long userId;
}

View File

@ -46,11 +46,6 @@ public class User {
*/ */
private String password; private String password;
/**
* 加密使用盐
*/
private String salt;
/** /**
* 邮箱 * 邮箱
*/ */

View File

@ -0,0 +1,122 @@
package asia.yulinling.workflow.model.vo.user;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* <p>
* 自定义User
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserPrincipal implements UserDetails {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 昵称
*/
private String nickname;
/**
* 加密后的密码
*/
@JsonIgnore
private String password;
/**
* 加密使用盐
*/
@JsonIgnore
private String salt;
/**
* 邮箱
*/
private String email;
/**
* 生日
*/
private String birthday;
/**
* 性别,-1,-2
*/
private Integer sex;
/**
* 手机号
*/
private String phone;
/**
* 状态 -1删除 0警用 1启用
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 上次更新时间
*/
private Date updateTime;
/**
* 上次登录时间
*/
private Date lastLoginTime;
/**
* 用户角色列表
*/
private List<String > roles;
/**
* 用户权限列表
*/
private Collection<? extends GrantedAuthority> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
}
@Override
public String getPassword() {
return "";
}
@Override
public String getUsername() {
return "";
}
}

View File

@ -0,0 +1,103 @@
package asia.yulinling.workflow.utils;
import asia.yulinling.workflow.config.JwtConfig;
import asia.yulinling.workflow.model.vo.user.UserPrincipal;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import io.jsonwebtoken.*;
import java.security.Key;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* <p>
* JWT工具类
* </p>
*
* @author YLL
* @since 2025/6/11
*/
@EnableConfigurationProperties(JwtConfig.class)
@Configuration
@RequiredArgsConstructor
@Slf4j
public class JwtUtil {
private final JwtConfig jwtConfig;
/**
* 创建JWT
*
* @param rememberMe 记住我
* @param id 用户id
* @param subject 用户名
* @param roles 用户角色
* @param authorities 用户权限
* @return JWT
*/
public String createJWT(Boolean rememberMe, Long id, String subject, List<String> roles, Collection<? extends GrantedAuthority> authorities) {
Date now = new Date();
Key key = Keys.hmacShaKeyFor(jwtConfig.getKey().getBytes());
JwtBuilder builder = Jwts.builder()
.setId(id.toString())
.setSubject(subject)
.setIssuedAt(now)
.signWith(key)
.claim("roles", roles)
.claim("authorities", authorities);
// 设置过期时间
Long ttl = rememberMe ? jwtConfig.getRemember() : jwtConfig.getTtl();
builder.setExpiration(new Date(now.getTime() + ttl));
return builder.compact();
}
/**
* 创建JWT
*
* @param authentication 用户认证信息
* @param rememberMe 记住我
* @return JWT
*/
public String createJWT(Authentication authentication, Boolean rememberMe) {
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
return createJWT(
rememberMe,
userPrincipal.getId(),
userPrincipal.getUsername(),
userPrincipal.getRoles(),
userPrincipal.getAuthorities()
);
}
public Claims parseJWT(String jwt) {
try {
// 1. 构建密钥
Key key = Keys.hmacShaKeyFor(jwtConfig.getKey().getBytes());
// 2. 使用 parserBuilder 构建解析器
Jws<Claims> jws = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(jwt);
Claims claims = jws.getBody();
String id = claims.getId();
String username = claims.getSubject();
return claims;
} catch (ExpiredJwtException e) {
log.error("ExpiredJwtException", e);
throw new JwtException("ExpiredJwtException");
}
}
}

View File

@ -37,3 +37,7 @@ spring.mail.properties.mail.smtp.ssl.enable=false
spring.mail.properties.mail.display.sendmail=spring-boot-demo spring.mail.properties.mail.display.sendmail=spring-boot-demo
# Jasypt配置 # Jasypt配置
jasypt.encryptor.password=abc jasypt.encryptor.password=abc
# JWT配置
jwt.config.key=kw
jwt.config.ttl=600000
jwt.config.remember=604800000

View File

@ -5,7 +5,6 @@ CREATE TABLE `wk_user`
`username` VARCHAR(32) NOT NULL UNIQUE COMMENT '用户名', `username` VARCHAR(32) NOT NULL UNIQUE COMMENT '用户名',
`nickname` VARCHAR(32) NOT NULL UNIQUE COMMENT '昵称', `nickname` VARCHAR(32) NOT NULL UNIQUE COMMENT '昵称',
`password` VARCHAR(32) NOT NULL COMMENT '加密后的密码', `password` VARCHAR(32) NOT NULL COMMENT '加密后的密码',
`salt` VARCHAR(32) NOT NULL COMMENT '加密使用的盐',
`email` VARCHAR(32) NOT NULL UNIQUE COMMENT '邮箱', `email` VARCHAR(32) NOT NULL UNIQUE COMMENT '邮箱',
`birthday` DATETIME DEFAULT NULL COMMENT '生日', `birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` INT(2) DEFAULT NULL COMMENT '性别,男-1,女-2', `sex` INT(2) DEFAULT NULL COMMENT '性别,男-1,女-2',