springBoot使用JWT实现单点登录

springBoot使用JWT实现单点登录

1.首先在项目的pom.xml中引入依赖

		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

2.封装一个TokenUtils

sign()方法传入用户的信息,使用JWT生成签名。
verify()方法用于验证签名,如果已失效,就返回false。
getUserId()用户获取token中的userId。
EXPIRE_TIME为token过期时间。

public class TokenUtils {

    private static final long EXPIRE_TIME= 15*60*1000;
    private static final String TOKEN_SECRET="tokenqkj";  //密钥盐


    /**
     * 签名生成
     * @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("userId", user.getId())
                    .withClaim("userName",user.getName())
                    .withExpiresAt(expiresAt)
                    // 使用了HMAC256加密算法。
                    .sign(Algorithm.HMAC256(TOKEN_SECRET));
        } catch (Exception e){
            e.printStackTrace();
        }
        return token;
    }

    /**
     * 签名验证,并返回用户的id
     * @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("userId: " + jwt.getClaim("userId").asString());
//            System.out.println("过期时间:      " + jwt.getExpiresAt());
            return true;
        } catch (Exception e){
            return false;
        }
    }
    /**
     * 获取token中的userId
     */
    public static String getUserId(String token){
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaim("userId").asString();
        } catch (Exception e){
            return null;
        }
    }
}

3.编写token拦截器

@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("token");
        if(token != null){
            boolean result = TokenUtils.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");
//            Map<String,Object> resMap = new HashMap<>();
//            resMap.put("code",50000);
//            resMap.put("message","未登录或登录失败");
//            response.getWriter().append(resMap.toString());
            System.out.println("认证失败,未通过拦截器");
            response.getWriter().write("50000");
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }

        return false;

    }

}

4.配置token拦截器

/**
 * 拦截器配置
 */
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {

    @Autowired(required = true)
    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("/user/login"); //登录
        excludePath.add("/logout"); //登出
        excludePath.add("/static/**");  //静态资源
        excludePath.add("/swagger-ui.html/**");  //静态资源
        excludePath.add("/assets/**");  //静态资源
        excludePath.add("/default/**");  //静态资源
        excludePath.add("/upload/**");  //静态资源
//        excludePath.add("/**");

        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);

    }

    /**
     * 跨域支持
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
                .maxAge(3600 * 24);
    }


}

5.前端配置拦截器

后端登录成功后返回token,前端储存起来,在之后每次发请求的时候带上token,如果请求返回的结果为50000,那么就表示未通过拦截器,用户未登录或者登录已失效。

/**
     * 用戶登录
     */
    @RequestMapping(value = "login",method = RequestMethod.POST)
    public ResponseResult login(User user){
        //根据前端输入的登录名和密码查询是否由该用户
        User queryUser = new User();
        queryUser.setLoginName(user.getLoginName());
        User queryUser1 = userService.getByEntity(queryUser);
        if(queryUser1==null){
            return new ResponseResult(ResponseCodeCanstants.FAILED,"没有该用户");
        }else{
            try {
                queryUser.setPassword(MD5Utils.EncoderByMd5(user.getPassword()));
                User queryUser2 = userService.getByEntity(queryUser);
                if(queryUser2==null){
                    return new ResponseResult(ResponseCodeCanstants.FAILED,"用户名或者密码失败");
                }
                String token = TokenUtils.sign(queryUser2);
                //定义结果集
//                Map<String,Object> resultMap = new HashMap<>();
//                resultMap.put("loginData", JSONArray.toJSON(queryUser2).toString());
//                resultMap.put("token",token);
                if(token!=null){
                    return new ResponseResult(ResponseCodeCanstants.SUCCESS,token,"登录成功");
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return new ResponseResult(ResponseCodeCanstants.FAILED,"登录出现错误");
        }

前端代码

// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  loading = Loading.service({
    lock: true,
    text: 'Loading',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.5)'
  });
  config.headers = {DeviceType: 'H5'};
  if (localStorage.getItem('token')) {
    config.headers.token = localStorage.getItem('token');
  }
  return config;
}, function (error) {
  // 对请求错误做些什么
  Message(error);
  console.log("========>", error);
  return Promise.reject(error);
});

之后每次发请求的时候就都会带上token了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值