全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解Spring Boot实战之Filter实现使用JWT进行接口认证

本文介绍了spring Boot实战之Filter实现使用JWT进行接口认证,分享给大家

jwt(json web token)

用户发送按照约定,向服务端发送 Header、Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api

jwt使用流程

本文示例接上面几篇文章中的代码进行编写,请阅读本文的同时可以参考前面几篇文章

1、添加依赖库jjwt,本文中构造jwt及解析jwt都使用了jjwt库

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

2、添加登录获取token时,所需要的认证信息类LoginPara.Java

package com.xiaofangtech.sunt.jwt; 
 
public class LoginPara { 
  private String clientId; 
  private String userName; 
  private String password; 
  private String captchaCode; 
  private String captchaValue; 
   
  public String getClientId() { 
    return clientId; 
  } 
  public void setClientId(String clientId) { 
    this.clientId = clientId; 
  } 
  public String getUserName() { 
    return userName; 
  } 
  public void setUserName(String userName) { 
    this.userName = userName; 
  } 
  public String getPassword() { 
    return password; 
  } 
  public void setPassword(String password) { 
    this.password = password; 
  } 
  public String getCaptchaCode() { 
    return captchaCode; 
  } 
  public void setCaptchaCode(String captchaCode) { 
    this.captchaCode = captchaCode; 
  } 
  public String getCaptchaValue() { 
    return captchaValue; 
  } 
  public void setCaptchaValue(String captchaValue) { 
    this.captchaValue = captchaValue; 
  } 
} 

3、添加构造jwt及解析jwt的帮助类JwtHelper.java

package com.xiaofangtech.sunt.jwt; 
 
import java.security.Key; 
import java.util.Date; 
 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 
 
import io.jsonwebtoken.Claims; 
import io.jsonwebtoken.JwtBuilder; 
import io.jsonwebtoken.Jwts; 
import io.jsonwebtoken.SignatureAlgorithm; 
 
public class JwtHelper { 
  public static Claims parseJWT(String jsonWebToken, String base64Security){ 
    try 
    { 
      Claims claims = Jwts.parser() 
            .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security)) 
            .parseClaimsJws(jsonWebToken).getBody(); 
      return claims; 
    } 
    catch(Exception ex) 
    { 
      return null; 
    } 
  } 
   
  public static String createJWT(String name, String userId, String role,  
      String audience, String issuer, long TTLMillis, String base64Security)  
  { 
    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; 
      
    long nowMillis = System.currentTimeMillis(); 
    Date now = new Date(nowMillis); 
      
    //生成签名密钥 
    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security); 
    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); 
      
     //添加构成JWT的参数 
    JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") 
                    .claim("role", role) 
                    .claim("unique_name", name) 
                    .claim("userid", userId) 
                    .setIssuer(issuer) 
                    .setAudience(audience) 
                    .signWith(signatureAlgorithm, signingKey); 
     //添加Token过期时间 
    if (TTLMillis >= 0) { 
      long expMillis = nowMillis + TTLMillis; 
      Date exp = new Date(expMillis); 
      builder.setExpiration(exp).setNotBefore(now); 
    } 
      
     //生成JWT 
    return builder.compact(); 
  }  
} 

4、添加token返回结果类AccessToken.java

package com.xiaofangtech.sunt.jwt; 
 
public class AccessToken { 
  private String access_token; 
  private String token_type; 
  private long expires_in; 
  public String getAccess_token() { 
    return access_token; 
  } 
  public void setAccess_token(String access_token) { 
    this.access_token = access_token; 
  } 
  public String getToken_type() { 
    return token_type; 
  } 
  public void setToken_type(String token_type) { 
    this.token_type = token_type; 
  } 
  public long getExpires_in() { 
    return expires_in; 
  } 
  public void setExpires_in(long expires_in) { 
    this.expires_in = expires_in; 
  } 
} 

5、添加获取token的接口,通过传入用户认证信息(用户名、密码)进行认证获取

package com.xiaofangtech.sunt.jwt; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.xiaofangtech.sunt.bean.UserInfo; 
import com.xiaofangtech.sunt.repository.UserInfoRepository; 
import com.xiaofangtech.sunt.utils.MyUtils; 
import com.xiaofangtech.sunt.utils.ResultMsg; 
import com.xiaofangtech.sunt.utils.ResultStatusCode; 
 
@RestController 
public class JsonWebToken { 
  @Autowired 
  private UserInfoRepository userRepositoy; 
   
  @Autowired 
  private Audience audienceEntity; 
   
  @RequestMapping("oauth/token") 
  public Object getAccessToken(@RequestBody LoginPara loginPara) 
  { 
    ResultMsg resultMsg; 
    try 
    { 
      if(loginPara.getClientId() == null  
          || (loginPara.getClientId().compareTo(audienceEntity.getClientId()) != 0)) 
      { 
        resultMsg = new ResultMsg(ResultStatusCode.INVALID_CLIENTID.getErrcode(),  
            ResultStatusCode.INVALID_CLIENTID.getErrmsg(), null); 
        return resultMsg; 
      } 
       
      //验证码校验在后面章节添加 
       
       
      //验证用户名密码 
      UserInfo user = userRepositoy.findUserInfoByName(loginPara.getUserName()); 
      if (user == null) 
      { 
        resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(), 
            ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null); 
        return resultMsg; 
      } 
      else 
      { 
        String md5Password = MyUtils.getMD5(loginPara.getPassword()+user.getSalt()); 
         
        if (md5Password.compareTo(user.getPassword()) != 0) 
        { 
          resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(), 
              ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null); 
          return resultMsg; 
        } 
      } 
       
      //拼装accessToken 
      String accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getName()), 
          user.getRole(), audienceEntity.getClientId(), audienceEntity.getName(), 
          audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret()); 
       
      //返回accessToken 
      AccessToken accessTokenEntity = new AccessToken(); 
      accessTokenEntity.setAccess_token(accessToken); 
      accessTokenEntity.setExpires_in(audienceEntity.getExpiresSecond()); 
      accessTokenEntity.setToken_type("bearer"); 
      resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(),  
          ResultStatusCode.OK.getErrmsg(), accessTokenEntity); 
      return resultMsg; 
       
    } 
    catch(Exception ex) 
    { 
      resultMsg = new ResultMsg(ResultStatusCode.SYSTEM_ERR.getErrcode(),  
          ResultStatusCode.SYSTEM_ERR.getErrmsg(), null); 
      return resultMsg; 
    } 
  } 
} 

6、添加使用jwt认证的filter

package com.xiaofangtech.sunt.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.context.support.SpringBeanAutowiringSupport; 
 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.xiaofangtech.sunt.jwt.Audience; 
import com.xiaofangtech.sunt.jwt.JwtHelper; 
import com.xiaofangtech.sunt.utils.ResultMsg; 
import com.xiaofangtech.sunt.utils.ResultStatusCode; 
 
public class HTTPBearerAuthorizeAttribute implements Filter{ 
  @Autowired 
  private Audience audienceEntity; 
 
  @Override 
  public void init(FilterConfig filterConfig) throws ServletException { 
    // TODO Auto-generated method stub 
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, 
        filterConfig.getServletContext()); 
     
  } 
 
  @Override 
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException { 
    // TODO Auto-generated method stub 
     
    ResultMsg resultMsg; 
    HttpServletRequest httpRequest = (HttpServletRequest)request; 
    String auth = httpRequest.getHeader("Authorization"); 
    if ((auth != null) && (auth.length() > 7)) 
    { 
      String HeadStr = auth.substring(0, 6).toLowerCase(); 
      if (HeadStr.compareTo("bearer") == 0) 
      { 
         
        auth = auth.substring(7, auth.length());  
        if (JwtHelper.parseJWT(auth, audienceEntity.getBase64Secret()) != null) 
        { 
          chain.doFilter(request, response); 
          return; 
        } 
      } 
    } 
     
    HttpServletResponse httpResponse = (HttpServletResponse) response; 
    httpResponse.setCharacterEncoding("UTF-8");  
    httpResponse.setContentType("application/json; charset=utf-8");  
    httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
 
    ObjectMapper mapper = new ObjectMapper(); 
     
    resultMsg = new ResultMsg(ResultStatusCode.INVALID_TOKEN.getErrcode(), ResultStatusCode.INVALID_TOKEN.getErrmsg(), null); 
    httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg)); 
    return; 
  } 
 
  @Override 
  public void destroy() { 
    // TODO Auto-generated method stub 
     
  } 
} 

7、在入口处注册filter

package com.xiaofangtech.sunt; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.context.embedded.FilterRegistrationBean; 
import org.springframework.boot.context.properties.EnableConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
 
import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute; 
import com.xiaofangtech.sunt.filter.HTTPBearerAuthorizeAttribute; 
import com.xiaofangtech.sunt.jwt.Audience; 
 
@SpringBootApplication 
@EnableConfigurationProperties(Audience.class) 
public class SpringRestApplication { 
 
  public static void main(String[] args) { 
    SpringApplication.run(SpringRestApplication.class, args); 
  } 
   
  @Bean 
  public FilterRegistrationBean basicFilterRegistrationBean() { 
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 
    HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute(); 
    registrationBean.setFilter(httpBasicFilter); 
    List<String> urlPatterns = new ArrayList<String>(); 
    urlPatterns.add("/user/getuser"); 
    registrationBean.setUrlPatterns(urlPatterns); 
    return registrationBean; 
  } 
   
  @Bean 
  public FilterRegistrationBean jwtFilterRegistrationBean(){ 
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 
    HTTPBearerAuthorizeAttribute httpBearerFilter = new HTTPBearerAuthorizeAttribute(); 
    registrationBean.setFilter(httpBearerFilter); 
    List<String> urlPatterns = new ArrayList<String>(); 
    urlPatterns.add("/user/getusers"); 
    registrationBean.setUrlPatterns(urlPatterns); 
    return registrationBean; 
  } 
} 

8、添加获取md5的方法类MyUtils

package com.xiaofangtech.sunt.utils; 
 
import java.security.MessageDigest; 
 
public class MyUtils { 
  public static String getMD5(String inStr) { 
    MessageDigest md5 = null; 
    try { 
      md5 = MessageDigest.getInstance("MD5"); 
    } catch (Exception e) { 
       
      e.printStackTrace(); 
      return ""; 
    } 
    char[] charArray = inStr.toCharArray(); 
    byte[] byteArray = new byte[charArray.length]; 
  
    for (int i = 0; i < charArray.length; i++) 
      byteArray[i] = (byte) charArray[i]; 
  
    byte[] md5Bytes = md5.digest(byteArray); 
  
    StringBuffer hexValue = new StringBuffer(); 
  
    for (int i = 0; i < md5Bytes.length; i++) { 
      int val = ((int) md5Bytes[i]) & 0xff; 
      if (val < 16) 
        hexValue.append("0"); 
      hexValue.append(Integer.toHexString(val)); 
    } 
  
    return hexValue.toString(); 
  } 
} 

9、在返回信息类中补充添加错误码

INVALID_CLIENTID(30003, "Invalid clientid"), 
INVALID_PASSWORD(30004, "User name or password is incorrect"), 
INVALID_CAPTCHA(30005, "Invalid captcha or captcha overdue"), 
INVALID_TOKEN(30006, "Invalid token"); 

10、代码中涉及的Audience类,在上一篇文章中定义,本文不再重复说明

11、代码整体结构

 

12、测试

1) 获取token,传入用户认证信息


认证通过返回token信息


2) 使用上面获取的token进行接口调用

未使用token,获取token错误,或者token过期时


使用正确的token时

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Spring  # Boot接口认证  # Boot  # 实现接口认证  # Vue+Jwt+SpringBoot+Ldap完成登录认证的示例代码  # Springboot集成Spring Security实现JWT认证的步骤详解  # SpringBoot整合SpringSecurity和JWT和Redis实现统一鉴权认证  # SpringBoot使用Jwt处理跨域认证问题的教程详解  # 详解SpringBoot如何使用JWT实现身份认证和授权  # 利用Springboot实现Jwt认证的示例代码  # springboot+jwt实现token登陆权限认证的实现  # SpringBoot整合SpringSecurity实现JWT认证的项目实践  # Spring Boot整合JWT实现认证与授权的项目实践  # 服务端  # 几篇  # 给大家  # 在后面  # 在上  # 验证码  # 所需要  # 适合于  # 用户发送  # 一篇文章  # 大家多多  # 类中  # 使用了  # 错误码  # setSigningKey  # builder  # typ  # setHeaderParam  # apiKeySecretBytes  # byte 


相关文章: ,网站推广常用方法?  为什么Go需要go mod文件_Go go mod文件作用说明  如何快速搭建响应式可视化网站?  香港服务器如何优化才能显著提升网站加载速度?  深圳网站制作平台,深圳市做网站好的公司有哪些?  专业公司网站制作公司,用什么语言做企业网站比较好?  陕西网站制作公司有哪些,陕西凌云电器有限公司官网?  定制建站策划方案_专业建站与网站建设方案一站式指南  如何用PHP工具快速搭建高效网站?  如何通过多用户协作模板快速搭建高效企业网站?  建站主机选购指南:核心配置与性价比推荐解析  高性能网站服务器配置指南:安全稳定与高效建站核心方案  如何通过免费商城建站系统源码自定义网站主题与功能?  网站制作模板下载什么软件,ppt模板免费下载网站?  大连网站设计制作招聘信息,大连投诉网站有哪些?  沈阳制作网站公司排名,沈阳装饰协会官方网站?  如何在VPS电脑上快速搭建网站?  如何快速重置建站主机并恢复默认配置?  建站主机与虚拟主机有何区别?如何选择最优方案?  Dapper的Execute方法的返回值是什么意思 Dapper Execute返回值详解  网站制作软件有哪些,制图软件有哪些?  如何用PHP快速搭建CMS系统?  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  相册网站制作软件,图片上的网址怎么复制?  零服务器AI建站解决方案:快速部署与云端平台低成本实践  如何选择网络建站服务器?高效建站必看指南  高端云建站费用究竟需要多少预算?  Swift中swift中的switch 语句  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  如何用花生壳三步快速搭建专属网站?  电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?  如何通过西部数码建站助手快速创建专业网站?  如何高效配置IIS服务器搭建网站?  怎么用手机制作网站链接,dw怎么把手机适应页面变成网页?  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  长沙做网站要多少钱,长沙国安网络怎么样?  如何快速搭建FTP站点实现文件共享?  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  如何在阿里云服务器自主搭建网站?  专业网站制作服务公司,有哪些网站可以免费发布招聘信息?  ,网页ppt怎么弄成自己的ppt?  高防服务器租用指南:配置选择与快速部署攻略  如何通过万网虚拟主机快速搭建网站?  湖北网站制作公司有哪些,湖北清能集团官网?  魔方云NAT建站如何实现端口转发?  高性价比服务器租赁——企业级配置与24小时运维服务  Thinkphp 中 distinct 的用法解析  建站之星24小时客服电话如何获取?  微网站制作教程,不会写代码,不会编程,怎么样建自己的网站?  网站专业制作公司有哪些,做一个公司网站要多少钱? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。