这个JWT工具类是我自己写的,具体怎么使用都在README.md中了
高度封装使用简单
git@gitee.com:giteeforsyf/jjwtutil.git
SpringBoot版本:2.7
SpringSecurity版本:5.4+
注:SpringSecurityConfigurationAdapter已过时
在准备工作中我们需要准备数据库、实体类、配置、工具类等

数据库设计如图:


cn.fly
JJWTUtil
1.1.2
mysql
mysql-connector-java
8.0.17
com.baomidou
mybatis-plus-boot-starter
3.5.1
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-web-services
org.springframework.boot
spring-boot-starter-data-redis
com.alibaba
fastjson
1.2.79
org.springframework.boot
spring-boot-devtools
runtime
true
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.security
spring-security-test
test
package com.example.ss1.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@TableName("user")
public class User {
private Long id;
private String username;
private String password;
private String status;
private String nickname;
}
package com.example.ss1.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.ss1.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper {
}
package com.example.ss1.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.ss1.entity.User;
import com.example.ss1.parm.LoginParam;
import com.example.ss1.util.ResultUtil;
public interface LoginService extends IService {
ResultUtil login(LoginParam loginParam);
}
package com.example.ss1.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultUtil {
private int code;
private String Message;
private Object data;
public static ResultUtil success(int code, String msg, Object data) {
ResultUtil ResultUtil = new ResultUtil();
ResultUtil.setCode(200);
ResultUtil.setMessage(msg);
ResultUtil.setData(data);
return ResultUtil;
}
public static ResultUtil success() {
return success(200, null, null);
}
public static ResultUtil success(String msg) {
return success(200, msg, null);
}
public static ResultUtil success(String msg, Object data) {
return success(200, msg, data);
}
public static ResultUtil fail(int code, String msg, Object data) {
ResultUtil ResultUtil = new ResultUtil();
ResultUtil.setCode(code);
ResultUtil.setMessage(msg);
ResultUtil.setData(data);
return ResultUtil;
}
public static ResultUtil fail(int code) {
return success(code, null, null);
}
public static ResultUtil fail(int code, String msg) {
return success(code, msg, null);
}
public static ResultUtil fail() {
return success(404, null, null);
}
}
package com.example.ss1.parm;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class LoginParam implements Serializable {
private String username;
private String password;
}
这里解释一下,由于我直接使用了我自己写的JJWTUtil所以这里只要将该类是设置为配置类继承JJWTUtil即可
package com.example.ss1.util;
import cn.fly.jjwtutil.JJWTUtil;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
@Configuration
@Data
public class JWTUtil extends JJWTUtil {
}
package com.example.ss1.controller;
import com.example.ss1.parm.LoginParam;
import com.example.ss1.service.LoginService;
import com.example.ss1.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("/user/login")
public ResultUtil login(@RequestBody LoginParam loginParam){
return loginService.login(loginParam);
}
}
对SpringSecurity的配置类,这里面编译器提示无法自动装配不用管

package com.example.ss1.config;
import com.example.ss1.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
public class SpringSecurityConfig {
@Autowired
private UserDetailsServiceImpl userDetailsService;
//获取AuthenticationManager(认证管理器),登录时认证使用
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
//配置过滤
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf().disable()//关闭csrf
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//关闭session
.and()
.authorizeRequests(auth ->
auth.antMatchers("/**").permitAll()
.anyRequest().authenticated()
)
.userDetailsService(userDetailsService).build();
}
//配置加密方式
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//配置跨源访问(CORS)
@Bean
CorsConfigurationSource corsConfigurationSource(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
package com.example.ss1.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.ss1.entity.User;
import com.example.ss1.entity.UserLogin;
import com.example.ss1.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询用户信息
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUsername, username).last("limit 1");
User user = userMapper.selectOne(queryWrapper);
//异常
if (Objects.isNull(user)){
throw new UsernameNotFoundException("用户名未发现");
}
//查询对应权限信息
//数据封装为UserDetails返回
return new UserLogin(user);
}
}
由于我们需要在UserDetailsServiceImpl中将数据进行封装
所以我们就需要有这样一个类实现UserDetails接口,定义返回的一系列方法
package com.example.ss1.entity;
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;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserLogin implements UserDetails {
//传入用户对象
private User user;
/**
* 判断权限信息
* @return
*/
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
/**
* 判断是否未过期
* @return
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 判断账户是否未锁定
* @return
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 判断是否可以使用
* @return
*/
@Override
public boolean isEnabled() {
return true;
}
}
package com.example.ss1.service.impl;
import cn.fly.jjwtutil.JJWTUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.ss1.entity.User;
import com.example.ss1.entity.UserLogin;
import com.example.ss1.mapper.UserMapper;
import com.example.ss1.parm.LoginParam;
import com.example.ss1.service.LoginService;
import com.example.ss1.util.JWTUtil;
import com.example.ss1.util.ResultUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class LoginServiceImpl extends ServiceImpl implements LoginService{
@Autowired
private JJWTUtil jjwtUtil;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public ResultUtil login(LoginParam loginParam) {
//进行用户认证。获取AuthenticationManager authenticate
//获取认证对象
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUsername(), loginParam.getPassword());
//认证
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//认证失败
if (Objects.isNull(authenticate)){
throw new RuntimeException("登录失败");
}
//认证成功,生成token
//获取用户信息(getPrincipal())
UserLogin user = (UserLogin) authenticate.getPrincipal();
Long id = user.getUser().getId();
Claims claims = Jwts.claims();
claims.put("userId",id);
jjwtUtil.defaultBuilder(jjwtUtil);
String token = jjwtUtil.createToken(claims);
System.out.println(token);
//返回
return ResultUtil.success("登录成功",token);
}
}
以下是调试结果,可以看到返回的用户信息是在Principal里的
其实在官网里很明确的说了


先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦