spring boot+jwt完成登录验证
本demo用于测试jwt,通过登录验证通过后,使用jwt生成token,然后在请求header中携带token完成访问用户列表信息。
准备工作:
在pom文件当中导入依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>4.12</version>
</dependency>
<!-- JWT依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
1.实体类User.java
package com.sdbairui.demo.Entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Table
@Entity(name="user")
public class User {
/*user id*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public User(String username,String password){
this.username = username;
this.password = password;
}
}
2.Mapper接口层UserDao.java
package com.sdbairui.demo.Dao;
import com.sdbairui.demo.Entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDao extends JpaRepository<User, Integer> {
}
3.Service接口
package com.sdbairui.demo.Service;
import com.sdbairui.demo.Entity.User;
import java.util.List;
public interface UserService {
public boolean login(User user);
public List<User> getList();
}
3.1Service接口工具类,用于实现获取用户的账号和密码用于验证
package com.sdbairui.demo.Service.impl;
import com.sdbairui.demo.Entity.User;
import com.sdbairui.demo.Service.UserService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Override
public boolean login(User user) {
String username = user.getUsername();
String password = user.getPassword();
if(username.equals("king") && password.equals("123")){
return true;
}
return false;
}
@Override
public List<User> getList() {
User user1= new User("king1","12345");
User user2 = new User("king2","12345");
User user3 = new User("king3","12345");
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
return list;
}
}
重点来了,接下来实现token工具类:
- 使用jwt完成签名生成方法与验证方法
package com.sdbairui.demo.Util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.sdbairui.demo.Entity.User;
import java.util.Date;
public class TokenUtil {
private static final long EXPIRE_TIME= 15*60*1000;
private static final String TOKEN_SECRET="token123"; //密钥盐
/**
* 签名生成
* @param user
* @return
*/
public static String sign(User user){
String token = null;
try {
Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME);
token = JWT.create()
.withIssuer("auth0")
.withClaim("username", user.getUsername())
.withExpiresAt(expiresAt)
// 使用了HMAC256加密算法。
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (Exception e){
e.printStackTrace();
}
return token;
}
/**
* 签名验证
* @param token
* @return
*/
public static boolean verify(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT jwt = verifier.verify(token);
System.out.println("认证通过:");
System.out.println("issuer: " + jwt.getIssuer());
System.out.println("username: " + jwt.getClaim("username").asString());
System.out.println("过期时间: " + jwt.getExpiresAt());
return true;
} catch (Exception e){
return false;
}
}
}
5.添加拦截器
package com.sdbairui.demo.Util;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
if(request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("admin-token");
if(token != null){
boolean result = TokenUtil.verify(token);
if(result){
System.out.println("通过拦截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try{
JSONObject json = new JSONObject();
json.put("success","false");
json.put("msg","认证失败,未通过拦截器");
json.put("code","50000");
response.getWriter().append(json.toJSONString());
System.out.println("认证失败,未通过拦截器");
// response.getWriter().write("50000");
}catch (Exception e){
e.printStackTrace();
response.sendError(500);
return false;
}
return false;
}
}
6.配置拦截器
package com.sdbairui.demo.Util;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* 拦截器配置
*/
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
private TokenInterceptor tokenInterceptor;
//构造方法
public IntercepterConfig(TokenInterceptor tokenInterceptor){
this.tokenInterceptor = tokenInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry){
List<String> excludePath = new ArrayList<>();
excludePath.add("/user_register"); //注册
excludePath.add("/login"); //登录
excludePath.add("/logout"); //登出
excludePath.add("/static/**"); //静态资源
excludePath.add("/assets/**"); //静态资源
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
- controller层实现登录方法和获取用户列表方法
package com.sdbairui.demo.Controller;
import com.sdbairui.demo.Entity.User;
import com.sdbairui.demo.Service.UserService;
import com.sdbairui.demo.Util.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping(value="/login")
@ResponseBody
public Map<String,Object> login(String username,String password){
Map<String,Object> map = new HashMap<>();
User user = new User(username,password);
if(userService.login(user)){
String token = TokenUtil.sign(user);
if(token != null){
map.put("code", "10000");
map.put("message", "认证成功");
map.put("token", token);
return map;
}
}
map.put("code", "0000");
map.put("message", "认证失败");
return map;
}
@PostMapping(value="/getList")
public List<User> getList(){
List userList = userService.getList();
return userList;
}
}
接下来测试:
- 使用postman提交登录信息,当密码故意输错时,返回验证失败。
- 提交正确的用户名和密码,验证通过,可以获取到token信息。
- 使用token信息放到header中,key设置为admin-token,然后请求用户列表信息。