SpringBoot集成Jwt(详细步骤+图解)
Jwt简介
JSON Web Token是目前最流行的跨域认证解决方案,,适合前后端分离项目通过Restful API进行数据交互时进行身份认证
Jwt构成(.隔开)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTkxNjQ4NjEsInVzZXJuYW1lIjoiYWRtaW4ifQ.fo5a-H_C7XG3fSnNdCEMzM2QmrF5c7yypzoSxGzgJOo
Header(头部):放有签名算法和令牌类型
Payload(负载):你在令牌上附带的信息:比如用户的姓名,这样以后验证了令牌之后就可以直接从这里获取信息而不用再查数据库了
Signature(签名):对前两部分的签名,防止数据篡改
交互流程
本文将通过几个简单步骤教大家如何集成Jwt,废话不多说,直接上步骤。(注:使用了Lombok,需下载好相关插件及依赖)
- 在项目的pom文件中加入Jwt依赖
<!---jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>
- 在项目的yml文件中配置账号密码
Login:
username: admin
password: admin
- 创建用户实体类
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;/**
* @author admin
*/@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{@NotNull(message ="id不能为空")private Integer id;@NotBlank(message="姓名不能为空")@Length(min =2, max =4, message ="name 姓名长度必须在 {min} - {max} 之间")private String username;@NotBlank(message="密码不能为空")@Length(min =5, max =10, message ="password 密码长度必须在 {min} - {max} 之间")private String password;}
- 创建Jwt(生成/验证)工具类
import com.auth0.jwt.JWT;import com.auth0.jwt.JWTCreator;import com.auth0.jwt.JWTVerifier;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.interfaces.DecodedJWT;import org.apache.commons.lang.StringUtils;import java.util.Calendar;/**
* @author admin
*/publicclassJWTUtils{/**
* 获取token
* @param u user
* @return token
*/publicstatic String getToken(User u){
Calendar instance = Calendar.getInstance();//默认令牌过期时间7天
instance.add(Calendar.DATE,7);
JWTCreator.Builder builder = JWT.create();
builder.withClaim("userId", u.getId()).withClaim("username", u.getUsername());return builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(u.getPassword()));}/**
* 验证token合法性 成功返回token
*/publicstatic DecodedJWT verify(String token)throws MyException {if(StringUtils.isEmpty(token)){thrownewMyException("token不能为空");}//获取登录用户真正的密码假如数据库查出来的是123456
String password ="admin";
JWTVerifier build = JWT.require(Algorithm.HMAC256(password)).build();return build.verify(token);}/* public static void main(String[] args) {
DecodedJWT verify = verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTcxMDg1MDAsInVzZXJuYW1lIjoiYWRtaW4ifQ.geBEtpluViRUg66_P7ZisN3I_d4e32Wms8mFoBYM5f0");
System.out.println(verify.getClaim("password").asString());
}*/}
- 创建Jwt拦截器(拦截所有请求验证token)
import com.auth0.jwt.exceptions.AlgorithmMismatchException;import com.auth0.jwt.exceptions.SignatureVerificationException;import com.auth0.jwt.exceptions.TokenExpiredException;import com.chentawen.springbootall.util.JWTUtils;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/**
* @author admin
*/@Slf4jpublicclassJWTInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
String token = request.getHeader("token");if(StringUtils.isEmpty(token)){thrownewMyException("token不能为空");}try{
JWTUtils.verify(token);}catch(SignatureVerificationException e){
log.error("无效签名! 错误 ->", e);returnfalse;}catch(TokenExpiredException e){
log.error("token过期! 错误 ->", e);returnfalse;}catch(AlgorithmMismatchException e){
log.error("token算法不一致! 错误 ->", e);returnfalse;}catch(Exception e){
log.error("token无效! 错误 ->", e);returnfalse;}returntrue;}}
- 将拦截器注入到SpirngMVC
import org.springframework.context.annotation.Configuration;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;/**
* @author admin
*/@ConfigurationpublicclassIntercaptorConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){
registry.addInterceptor(newJWTInterceptor())//拦截的路径.addPathPatterns("/**")//排除登录接口.excludePathPatterns("/user/login");}
- 创建Controller进行测试
import org.springframework.beans.factory.annotation.Value;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;/**
* @author admin
*/@RestController@RequestMapping("user")publicclassUserLoginController{@Value("${Login.username}")private String realUsername;@Value("${Login.password}")private String realPassword;@GetMapping("login")public String login(String username, String password){if(username.equals(realUsername)&& password.equals(realPassword)){
User u =newUser();
u.setPassword(password);
u.setUsername(username);return JWTUtils.getToken(u);}return"登录失败!账号或者密码不对!";}@GetMapping("test")public String test(){return"访问test - API";}}
- 使用Postman进行测试
登录接口-返回Jwt
测试接口-返回无权限
测试接口-请求头带token,访问成功
有什么疑问可评论区提问! 求点赞!求转发!求收藏!
版权归原作者 撸码社区 所有, 如有侵权,请联系我们删除。