前后端分离:SpringBoot + Jwt 登录验证token

前后端分离:SpringBoot + Jwt 登录验证token

写在前面:近期在做一个前后台分离的项目 Springboot + vue 登录验证的时候选用了shiro 因为是拿来即用的 所以前后端部署完成后出现很多bug...   种种原因 最后选择了友好又亲切的Jwt  : )

好了 直接上代码了

wait 粗暴上代码之前让我先小小说下这个小模块是什么原理 (毕竟鱼的记忆力)

以我的理解的来说的话 Jwt相当于一个令牌 一旦用户成功登录 服务器端就会给用户办法一个令牌 用户后续的每一次请求 都会带着这个令牌 服务器将会校验这个令牌 允许该用户访问该令牌允许的路由,服务和资源 这个令牌能够轻松地跨不同域使用

 

Jwt(JSON Web Tokens)的令牌结构

在紧凑的形式中,Jwt 包含三个由(.)分隔得部分

  • 有效载荷

  • 签名

因此,Jwt 通常看起来为  xxxx.yyyy.zzzz

 

通常由两部分组成:令牌的类型,即JWT和正在使用的散列算法,如HMAC SHA256或RSA。

例如:

{

"alg": "HS256",

"typ": "JWT"

}

然后,这个JSON被Base64Url编码,形成JWT的第一部分。

 

有效载荷

令牌的第二部分是包含声明的有效负载。声明是关于实体(通常是用户)和其他元数据的声明。

例如:

{

"sub": "1234567890",

"name": "John Doe",

"admin": true

}

有效载荷会根据自己业务需求来编写 其中还包括 iss(发行者), exp(到期时间), sub(主题), aud(受众)等

这个JSON被Base64Url编码,形成JWT的第二部分。

请注意,对于已签名的令牌,此信息尽管受到篡改保护,但任何人都可以阅读。除非加密,否则不要将秘密信息放在JWT的有效内容或标题元素中。

 

签名

要创建签名部分,您必须采用编码标头,编码有效载荷,秘密,标头中指定的算法并签名

例如,如果你想使用HMAC SHA256算法,签名将按照以下方式创建:

HMACSHA256(

base64UrlEncode(header) + "." +

base64UrlEncode(payload),

secret)

输出是三个由点分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递,而与基于XML的标准(如SAML)相比,它更加紧凑。

Jwt 部分如果想了解的更加详细的话 可以参考:https://ninghao.net/blog/2834

好了 大概就讲这么多 开始上代码了

1、首先 编写一个生成token 的工具类

public class JwtUtil {

    final static String base64EncodedSecretKey = "你的私钥";//私钥

    final static long TOKEN_EXP = 1000 * 60 * 10;//过期时间,测试使用十分钟



    public static String getToken(String userName) {

        return Jwts.builder()

                .setSubject(userName)

                .claim("roles", "user")

                .setIssuedAt(new Date())

                .setExpiration(new Date(System.currentTimeMillis() + TOKEN_EXP)) /*过期时间*/

                .signWith(SignatureAlgorithm.HS256, base64EncodedSecretKey)

                .compact();

    }

}

 

2、在用户登录时 校验信息有效后 将token信息返回给客户端

/**

* 用户登录

* @param userPo

* @return

*/

@PostMapping("/login")

public ResponseResult<String> login(@RequestBody UserPo userPo) {

    String pwd = SHAUtils.encodeData(userPo.getPassword());

    userPo.setPassword(pwd);

    userService.findUserVoByUsernameAndPassword(userPo);

    String token = JwtUtil.getToken(userPo.getUsername());

    return new ResponseResult<>("Bearer:" + token);

}

3、好了 要开始写拦截器了 用户在登录后的每次请求 都会经过这个拦截器 校验token是否有效

import cn.yuchen.fr.utility.JwtInterceptor;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;



@Configuration

public class WebConfig implements WebMvcConfigurer {

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

        //添加拦截器

        registry.addInterceptor(new JwtInterceptor()).excludePathPatterns("/login","/user/hello");//放掉某些特定不需要校验token的路由

    }

}

4、拦截器 JwtInterceptor()

import io.jsonwebtoken.Claims;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class JwtInterceptor extends HandlerInterceptorAdapter {

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String authHeader = request.getHeader("Authorization");

        if (authHeader == null || !authHeader.startsWith("Bearer:")) {

            throw new UserLoginException("用户未登录");

        }

        //取得token

        String token = authHeader.substring(7);

        //验证token

        Claims claims = JwtUtil.checkToken(token);

        request.setAttribute("username",claims.getSubject());

        return true;

    }

}

5、 校验 Jwt 的工具类

/**

* 检查token,只要不正确就会抛出异常

**/

public static Claims checkToken(String token) throws ServletException {

    try {

        final Claims claims = Jwts.parser().setSigningKey(base64EncodedSecretKey).parseClaimsJws(token).getBody();

        return claims;

    } catch (ExpiredJwtException e1) {

        throw new UserLoginInvalidException("登录信息过期,请重新登录");

    } catch (Exception e) {

        throw new UserLoginException("用户未登录,请重新登录");

    }

}

到这里 后台部分就完成了 现在你只要和你前端小哥哥 or 小姐姐 约定好 登陆成功后 每次请求时将token放在requestHeader中就好了

wait wait 跨域 这个忘了写

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

好了 下班了回家啦 :)

如果有什么问题 欢迎指正

ps:补上SHAUtils

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHAUtils {

    public static String encodeData(String str){
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(str.getBytes());
            byte byteData[] = md.digest();

            //将字节转换为十六进制格式方法一
            StringBuffer sb = new StringBuffer();
            for(int i = 0; i < byteData.length; i++){
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }
            System.out.println("Hex format : " + sb.toString());
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
}

  • 20
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
Spring Boot和Vue.js是两个非常流行的技术栈,可以非常好地实现前后端分离的开发模式。Security和JWT是两个很好的工具,可以帮助我们实现安全的登录和授权机制。 以下是实现Spring Boot和Vue.js前后端分离的步骤: 1.创建Spring Boot工程 首先,我们需要创建一个Spring Boot工程,可以使用Spring Initializr来生成一个基本的Maven项目,添加所需的依赖项,包括Spring Security和JWT。 2.配置Spring Security 在Spring Security中,我们需要定义一个安全配置类,该类将定义我们的安全策略和JWT的配置。在这里,我们可以使用注解来定义我们的安全策略,如@PreAuthorize和@Secured。 3.实现JWT JWT是一种基于令牌的身份验证机制,它使用JSON Web Token来传递安全信息。在我们的应用程序中,我们需要实现JWT的生成和验证机制,以便我们可以安全地登录和授权。 4.配置Vue.js 在Vue.js中,我们需要创建一个Vue.js项目,并使用Vue CLI来安装和配置我们的项目。我们需要使用Vue Router来定义我们的路由,并使用Axios来发送HTTP请求。 5.实现登录和授权 最后,我们需要实现登录和授权机制,以便用户可以安全地登录和访问我们的应用程序。在Vue.js中,我们可以使用Vue Router和Axios来发送HTTP请求,并在Spring Boot中使用JWT验证用户身份。 总结 以上是实现Spring Boot和Vue.js前后端分离的步骤,我们可以使用Security和JWT来实现安全的登录和授权机制。这种开发模式可以让我们更好地实现前后端分离,提高我们的开发效率和应用程序的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值