SpringBoot中如何使用jwt来保护接口数据

在使用springboot能够很方便的写接口,但是这些接口都是暴漏出来的,没有安全验证,任何人都可以调用显然这是不合理的。如果加个注册登录模块,只有登陆的用户才能调用,那么当你这个服务在N多节点部署时候,session共享又要解决,增加额外的开销。个人项目中使用的是jwt这个技术,简单说就是当你登陆成功后服务器会给你一个令牌,你拿着这个令牌去访问每个接口,服务器会对你的令牌进行鉴权,服务器能够知道你是谁,是否有权限。当在多个节点部署时候,每台服务器都是可以解析的。如果你有更好的解决方案,还请多多指教。下面说下我是怎么做的。本文是在一个springboot的Web项目基础上的。

思路:1.引入jwt的jar包 2.配置一个拦截器 并定义拦截路径 3.注册这个拦截器

注意:在拦截器里面拦截到请求后,进行令牌鉴权。比如查看用户角色,用户登陆时间,令牌是否过期等。在决定是否放行。

第一步:在springboot的web项目基础上添加jwt的jar包

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.6.0</version> </dependency>

第二步:配置一个拦截器,并定义拦截路径和规则,注意:secretkey是加解密的密钥、实际使用中替换成你自己的。

完整代码如下:

public class Filterdemo implements Filter { private static Set<String> path = new HashSet<String>(); // 不拦截的路径 static { path.add("/"); path.add("/favicon.ico"); path.add("/open"); path.add("/getcode"); path.add("/error"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("1.自定义过滤器初始化------"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String url = request.getRequestURI(); System.out.println("过滤器启动,---请求地址:" + url); // 获取header final String authHeader = request.getHeader("authorization"); //检查请求接口路径是否在允许的setif (path.contains(url)) { filterChain.doFilter(request, response); } else { // 检查 authorization,并检查是否以 "Bearer "开头,注意有一个空格 if (authHeader == null || !authHeader.startsWith("Bearer ")) { throw new ServletException("认证信息为空或者认证信息不正确"); } // 截取字符串,截取token final String token = authHeader.substring(7); try { // 解密token final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody(); //tokenrequest,此处应根据自己实际业务进行 request.setAttribute("claims", claims); } catch (final SignatureException e) { throw new ServletException("Invalid token"); } filterChain.doFilter(servletRequest, servletResponse); } } @Override public void destroy() { System.out.println("自定义过滤器销毁"); }

这里是拦截到请求的处理,实际上在用户登陆后就应该给用户颁发令牌,代码如下:

@RequestMapping("/login") @ResponseBody public String login(String userName, String passwd) { //此处仅判断不为空就认为是合法用户,登陆成功 if (userName != null && passwd != null) { // 生成jwt token返回给前台 String jwtToken = Jwts.builder() //JWT所面向的用户,是否使用是可选的; .setSubject(userName) //自己希望存储的数据,比如角色,可以放多个 .claim("roles", "member") .claim("menu", "xxx") //颁发时间 .setIssuedAt(new Date()) //加密算法和秘钥 .signWith(SignatureAlgorithm.HS256, "secretkey").compact(); return jwtToken; } else { System.out.println("用户名或密码为空"); } return "hello"; }

第三步:注册这个拦截器,注册到系统里

@Configuration public class filterConfig {

@Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); //设定我们写的拦截器对象 filterRegistrationBean.setFilter(new Filterdemo()); //设定拦截路径 filterRegistrationBean.addUrlPatterns("/**"); //设置启动顺序,多个拦截器时候使用 filterRegistrationBean.setOrder(2); return filterRegistrationBean; } }