SpringSecurity集成JWT
JWT简介
JWT是JSON Web Token的缩写,是一种开放的标准,JWT定义了一种紧凑且自包含的标准,该标准旨在将各个主体的信息标准包装JSON对象。主体信息是通过数字签名进行加密和验证的。常使用HMAC算法或者RSA(公钥/私钥的非堆成加密算法)算法对JWT进行签名,安全性很高。
结构
JWT分为三段式, xxxx.yyyyyyyyy.zzzzz
通常包含三个部分
1:Header
{
"algorithm":"RSA",//表明是哪种算法, RSA或者 SHA256 或者 HMAC
"type":"JWT" //令牌类型
}
2:Payload
//包含了用户信息, Claim等,有三种类型,公开,保留,私人
{
"id":"879c21cc040a4fbe23729cee4628568e",
"name":"Calvin",
"age":"18",
"gender":"1",
"isAdmin":"1"
}
3:Signature
/**
* 生成一个JWT
*@param header 头部信息
*@param payload 主体
*/
public String encriptJWT(Object header, Object payload, String secret){
encript(Base64.encode(header) + "." + Base64.encode(payload), secret);
}
编码
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.calvin.boot</groupId>
<artifactId>boot-security-jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot-security-jwt</name>
<dependencies>
<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>
</dependency>
<!-- jwt -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
application.yml
server:
port: 8080
spring:
application:
name: boot-security-jwt
datasource:
url: jdbc:mysql://localhost:3306/security_jwt?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useAffectedRows=true&useSSL=false&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
jwt:
expiration: 7200000
secret: calvin
token: Authorization
先写几个比较基础的类 SysUser 继承 UserDetails,重写几个关键方法,其中getAuthorities方法被我改动,注意泛型
import org.springframework.security.core.userdetails.UserDetails;
/**
* <p> 系统级用户</p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
public class SysUser implements UserDetails {
/**
* ID
*/
private String id;
/**
* 头像
*/
private String headImg;
/**
* 性别
*/
private Integer gender;
/**
* 年龄
*/
private Integer age;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 账户
*/
private String account;
/**
* 权限列表
*/
@TableField(exist = false)
private List<SysRole> roleList;
/**
* 创建时间
*/
private Date createTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHeadImg() {
return headImg;
}
public void setHeadImg(String headImg) {
this.headImg = headImg;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public List<SysRole> getAuthorities() {
return roleList;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("SysUser{");
sb.append("id='").append(id).append('\'');
sb.append(", headImg='").append(headImg).append('\'');
sb.append(", gender=").append(gender);
sb.append(", age=").append(age);
sb.append(", username='").append(username).append('\'');
sb.append(", password='").append(password).append('\'');
sb.append(", account='").append(account).append('\'');
sb.append(", roleList=").append(roleList);
sb.append(", createTime=").append(createTime);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SysUser sysUser = (SysUser) o;
return Objects.equals(id, sysUser.id) &&
Objects.equals(headImg, sysUser.headImg) &&
Objects.equals(gender, sysUser.gender) &&
Objects.equals(age, sysUser.age) &&
Objects.equals(username, sysUser.username) &&
Objects.equals(password, sysUser.password) &&
Objects.equals(account, sysUser.account) &&
Objects.equals(roleList, sysUser.roleList) &&
Objects.equals(createTime, sysUser.createTime);
}
@Override
public int hashCode() {
return Objects.hash(id, headImg, gender, age, username, password, account, roleList, createTime);
}
}
SysRole类继承GrantedAuthority,重写getAuthority方法
import org.springframework.security.core.GrantedAuthority;
/**
* <p> 简单用户权限类 </p>
*
* @author Calvin
* @see com.calvin.boot.sys.service.SysUserDetailService
* @see SysUser
* @date 2019/09/06
* @since
*/
public class SysRole implements GrantedAuthority {
private static final long serialVersionUID = -7511279890897762933L;
/**
* id
*/
private String id;
/**
* 角色名称
*/
private String authority;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setAuthority(String authority) {
this.authority = authority;
}
@Override
public String getAuthority() {
return authority;
}
}
相关sql
# 创建数据库
create database security_jwt;
use security_jwt;
# 创建用户表
drop table if exists sys_user;
create table sys_user (
id varchar(40) primary key ,
username varchar(20),
password varchar(32),
age int ,
account varchar(50),
head_img varchar(255),
gender int,
create_time datetime
);
# 创建权限表
create table sys_role (
id varchar(40) primary key ,
authority varchar(40)
);
# 用户权限映射表
create table sys_user_role(
id varchar(40) primary key ,
user_id varchar(40),
role_id varchar(40),
delete_flag int(1)
);
# 用户记录
insert into sys_user(id, head_img, gender,age,username, password, account,create_time)
values('1',null,1,20,'admin','e10adc3949ba59abbe56e057f20f883e', 'admin@account.com',now());
# 权限记录
insert into sys_role values ('1','ROLE_USER');
insert into sys_role values ('2','ROLE_ADMIN');
insert into sys_role values ('3','ROLE_GUEST');
# 插入映射关系
insert into sys_user_role values('1','1','1','0');
SysUserMapper && SysRoleMapper
/**
* <p> 用户的Mapper</p>
*
* @author Calvin
* @date 2019/09/06
* @see com.calvin.boot.service.impl.SysUserServiceImpl
* @since
*/
@Mapper
public interface ISysUserMapper extends BaseMapper<SysUser> {
}
------------------------------------------------------------------------
package com.calvin.boot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.calvin.boot.entity.SysRole;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* <p> 角色Mapper </p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
@Mapper
public interface ISysRoleMapper extends BaseMapper<SysRole> {
/**
* 多表联查,用户权限
* @param userId
* @return
*/
@Select("select a.id, a.authority from sys_role a join sys_user_role b on a.id = b.role_id where b.user_id = ${userId}")
List<SysRole> selectByUserId(@Param("userId") String userId);
}
以下是核心,请重点关注
LoginController
/**
* <p>
* 登录相关的controller
* </p>
* @author Calvin
*/
@RestController
@RequestMapping("/login")
public class LoginController {
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Autowired
private AuthenticationManager myAuthenticationManager;
/**
* 登录接口
* @param username
* @param password
* @return
*/
@RequestMapping("/userLogin")
public MessageEntity userLogin(String username, String password){
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(username, password);
Authentication authenticate = myAuthenticationManager.authenticate(token);
SysUser sysUser = (SysUser) authenticate.getPrincipal();
String jwtToken = jwtTokenUtils.generateToken(sysUser);
MessageEntity messageEntity = new MessageEntity();
messageEntity.setCode(200);
messageEntity.setMsg("success");
messageEntity.setData(jwtToken);
return messageEntity;
}
/**
* 重新登录消息
* @return
*/
@RequestMapping("/message")
public MessageEntity loginMessage(){
MessageEntity messageEntity = new MessageEntity();
messageEntity.setCode(MessageCode.CREDENTIAL_EXPIRED);
messageEntity.setData(null);
messageEntity.setMsg("you need login!");
return messageEntity;
}
}
SysUserDetailService 核心类之一
/**
* <p>UserDetailsService实现, Security核心类之一 </p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
@Service
public class SysUserDetailService implements UserDetailsService {
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysRoleService sysRoleService;
private static final Logger log = LoggerFactory.getLogger(SysUserDetailService.class);
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser byUsername = sysUserService.findByUsername(username);
if(byUsername == null){
log.warn("not found username for : {}", username);
throw new UsernameNotFoundException("不存在的账户");
}
List<SysRole> roles = sysRoleService.listByUserId(byUsername.getId());
byUsername.setRoleList(roles);
return byUsername;
}
}
ISysUserService
/**
* <p> 用户相关的Service</p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
public interface ISysUserService{
/**
* 根据用户名查找
* @param username
* @return
*/
SysUser findByUsername(String username);
}
ISysRoleService
/**
* <p>
* 角色相关的Service
* </p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
public interface ISysRoleService {
/**
* 根据用户名查询到所有角色
* @param userId
* @return
*/
List<SysRole> listByUserId(String userId);
}
JwtTokenUtils
package com.calvin.boot.sys.tools;
import com.calvin.boot.entity.SysUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClaims;
import io.jsonwebtoken.impl.DefaultClock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Map;
/**
* <p> JwtToken生成器</p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
@Component
public class JwtTokenUtils implements Serializable {
private static final long serialVersionUID = 3069830602400919900L;
@Value("${jwt.token}")
private String jwtHeader;
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expiration}")
private Long jwtExpiration;
private Clock clock = DefaultClock.INSTANCE;
/**
* 生成一个token
* @param sysUser
* @return
*/
public String generateToken(SysUser sysUser){
Claims claims = new DefaultClaims();
claims.put("id", sysUser.getId());
claims.put("username", sysUser.getUsername());
claims.put("password", sysUser.getPassword());
claims.put("account", sysUser.getAccount());
claims.put("age", sysUser.getAge());
claims.put("gender", sysUser.getGender());
claims.put("createTime", sysUser.getCreateTime());
return doGenerateToken(claims, sysUser.getId());
}
/**
* 生成一个token
* @param claims
* @param username
* @return
*/
private String doGenerateToken(Map<String, Object> claims, String username) {
final Date createDate = clock.now();
final Date expirationDate = calculateExpirationDate(createDate);
return Jwts.builder().setClaims(claims)
.setSubject(username)
.setIssuedAt(createDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
/**
* 计算过期时间
* @param createDate
* @return
*/
private Date calculateExpirationDate(Date createDate) {
long expiration = createDate.getTime() + jwtExpiration;
return new Date(expiration);
}
/**
* 验证token
* @param token
* @param userDetails
* @return
*/
public Boolean validateToken(String token, UserDetails userDetails) {
SysUser user = (SysUser) userDetails;
SysUser userForm = null;
try {
userForm = parseClaimToSysUser(getClaimFromToken(token));
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (userForm.getUsername().equals(user.getUsername())
&& !isTokenExpired(token)
);
}
/**
* 验证token是否过期
* @param token
* @return
*/
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
/**
* 获取token的过期时间
* @param token
* @return
*/
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token).getExpiration();
}
/**
* 将claims转换成SysUser
* @param claims
* @return
*/
public SysUser parseClaimToSysUser(Claims claims) throws InvocationTargetException, IllegalAccessException {
SysUser result = new SysUser();
result.setId((String) claims.get("id"));
result.setUsername((String) claims.get("username"));
result.setPassword((String) claims.get("password"));
result.setAccount((String) claims.get("account"));
result.setGender((Integer) claims.get("gender"));
result.setAge((Integer) claims.get("age"));
result.setCreateTime((Date) claims.get("createTime"));
return result;
}
/**
* 从jwt中解析出Claims
* @param token
* @return
*/
public Claims getClaimFromToken(String token){
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
}
}
package com.calvin.boot.sys.filter;
import com.calvin.boot.sys.service.SysUserDetailService;
import com.calvin.boot.sys.tools.JwtTokenUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
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;
/**
* <p>核心过滤器,判断是否具备权限,是否需要校验 </p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.token}")
private String jwtHeader;
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Autowired
private SysUserDetailService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
logger.info("do jwt authorization token filter for url: " + httpServletRequest.getRequestURI());
final String token = httpServletRequest.getHeader(this.jwtHeader);
if(token != null){
Claims claims = jwtTokenUtils.getClaimFromToken(token);
String username = claims.get("username",String.class);
UserDetails sysUser = this.userDetailsService.loadUserByUsername(username);
if(jwtTokenUtils.validateToken(token, sysUser)){
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(httpServletRequest,httpServletResponse);
}
}
package com.calvin.boot.config;
import com.calvin.boot.sys.filter.JwtAuthorizationTokenFilter;
import com.calvin.boot.sys.filter.JwtLoginFilter;
import com.calvin.boot.sys.service.SysUserDetailService;
import com.calvin.boot.sys.tools.Md5PasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* <p>
* SpringSecurity核心配置类
* </p>
*
* @author Calvin
* @date 2019/09/06
* @since 0.1
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SysUserDetailService sysUserDetailService;
@Autowired
private JwtAuthorizationTokenFilter jwtAuthorizationTokenFilter;
/**
* 简单配置过滤和校验
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new JwtAuthorizationEntryPoint())
.and().authorizeRequests()
.antMatchers("/login/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
.anyRequest().authenticated()
.and().
csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtAuthorizationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
/**
* 配置密码转换器和UserDetailService
* @param builder 校验管理器
* @throws Exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(sysUserDetailService).passwordEncoder(passwordEncoder());
}
/**
* 密码管理器的Bean配置
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
/**
* 配置权限校验器Bean
* @return
* @throws Exception
*/
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
JwtAuthorizationEntryPoint
/**
* <p>
* 如果没有凭证的处理,跳转回登录页面
* </p>
* @author jiawentao
* @date 2019/09/11
* @since
*/
public class JwtAuthorizationEntryPoint implements org.springframework.security.web.AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthorizationEntryPoint.class);
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
logger.info("there is an request without authorization{}, remote url is {}", httpServletRequest.getRequestURL(), httpServletRequest.getRemoteHost());
httpServletResponse.sendRedirect("/login/message");
}
}
MD5PasswordEncoder
/**
* <p>
* MD5PasswordEncoder进行字符串加密和判断是否匹配
* </p>
* @see org.springframework.security.crypto.password.PasswordEncoder
* @see com.calvin.boot.config.SecurityConfig
* @author Calvin
* @date 2019/09/06
* @since v0.1
*/
public class Md5PasswordEncoder implements PasswordEncoder {
/**
* 对字符串进行MD5加密, 32位小写
* @param charSequence 要加密的字符串
* @return
*/
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
}
/**
* 判断密码是否正确,先把新的字符串加密
* @param charSequence 未加密的字符串
* @param s 已经加密过的字符串
* @return
*/
@Override
public boolean matches(CharSequence charSequence, String s) {
return this.encode(charSequence).equals(s);
}
}
OrderController(用作测试)
/**
* <p>测试 </p>
*
* @author Calvin
* @date 2019/09/06
* @since
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@RequestMapping("/test")
public String testOrder(){
return "success";
}
}
至此大概写结束了,有小部分代码,实体封装和异常封装的类,代码就不贴上来了 现在进行登录测试
验证token
注解式参数
1:定义注解
/**
* <p> 注解到参数的当前登录用户</p>
*
* @author jiawentao
* @date 2019/09/15
* @since
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginUser {
}
注解解析器,通过JwtTokenUtils解析Header中的token直接拿到SysUser
/**
* <p> LoginUser注解参数获取当前用户</p>
*
* @author jiawentao
* @date 2019/09/15
* @since
*/
@Component
public class LoginUserHandlerResolver implements HandlerMethodArgumentResolver {
@Value("${jwt.token}")
private String jwtHeader;
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(SysUser.class)
&& parameter.hasParameterAnnotation(LoginUser.class);
}
/**
* 将参数解析成实体
* @param parameter 方法参数
* @param mavContainer 视图容器
* @param webRequest 本地请求
* @param binderFactory 参数绑定
* @return
* @throws Exception
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String header = webRequest.getHeader(jwtHeader);
return jwtTokenUtils.parseClaimToSysUser(jwtTokenUtils.getClaimFromToken(header));
}
}
配置参数解析器
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Autowired
private LoginUserHandlerResolver loginUserHandlerResolver;
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserHandlerResolver);
}
}
小结
1:简单使用SpringBootSecurity做了一个权限校验
2:融入进JWT令牌
3:编写注解式获取当前登录用户信息
问题总结
1: 对SpringBootSecurity框架了解不够详细,只能简单使用,也是导致这次更新时间比较长的原因
2: 没有融入进redis等缓存服务,导致此项目暂时不支持集群部署
3:直接采用Mybatis-Plus框架,对没有Mbatis基础的同学不友好
4:应该更加注重编码规范和注释,贴代码的过程中才发现注释太少