zoukankan      html  css  js  c++  java
  • [转] Spring Boot实战之Filter实现使用JWT进行接口认证

    【From】 http://blog.csdn.net/sun_t89/article/details/51923017

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

    jwt(json web token)

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

    jwt使用流程

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

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

                   

    [html] view plain copy
     
    1. <dependency>  
    2.     <groupId>io.jsonwebtoken</groupId>  
    3.     <artifactId>jjwt</artifactId>  
    4.     <version>0.6.0</version>  
    5. </dependency>  



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

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.jwt;  
    2.   
    3. public class LoginPara {  
    4.     private String clientId;  
    5.     private String userName;  
    6.     private String password;  
    7.     private String captchaCode;  
    8.     private String captchaValue;  
    9.       
    10.     public String getClientId() {  
    11.         return clientId;  
    12.     }  
    13.     public void setClientId(String clientId) {  
    14.         this.clientId = clientId;  
    15.     }  
    16.     public String getUserName() {  
    17.         return userName;  
    18.     }  
    19.     public void setUserName(String userName) {  
    20.         this.userName = userName;  
    21.     }  
    22.     public String getPassword() {  
    23.         return password;  
    24.     }  
    25.     public void setPassword(String password) {  
    26.         this.password = password;  
    27.     }  
    28.     public String getCaptchaCode() {  
    29.         return captchaCode;  
    30.     }  
    31.     public void setCaptchaCode(String captchaCode) {  
    32.         this.captchaCode = captchaCode;  
    33.     }  
    34.     public String getCaptchaValue() {  
    35.         return captchaValue;  
    36.     }  
    37.     public void setCaptchaValue(String captchaValue) {  
    38.         this.captchaValue = captchaValue;  
    39.     }  
    40. }  

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

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.jwt;  
    2.   
    3. import java.security.Key;  
    4. import java.util.Date;  
    5.   
    6. import javax.crypto.spec.SecretKeySpec;  
    7. import javax.xml.bind.DatatypeConverter;  
    8.   
    9. import io.jsonwebtoken.Claims;  
    10. import io.jsonwebtoken.JwtBuilder;  
    11. import io.jsonwebtoken.Jwts;  
    12. import io.jsonwebtoken.SignatureAlgorithm;  
    13.   
    14. public class JwtHelper {  
    15.     public static Claims parseJWT(String jsonWebToken, String base64Security){  
    16.         try  
    17.         {  
    18.             Claims claims = Jwts.parser()  
    19.                        .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))  
    20.                        .parseClaimsJws(jsonWebToken).getBody();  
    21.             return claims;  
    22.         }  
    23.         catch(Exception ex)  
    24.         {  
    25.             return null;  
    26.         }  
    27.     }  
    28.       
    29.     public static String createJWT(String name, String userId, String role,   
    30.             String audience, String issuer, long TTLMillis, String base64Security)   
    31.     {  
    32.         SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;  
    33.            
    34.         long nowMillis = System.currentTimeMillis();  
    35.         Date now = new Date(nowMillis);  
    36.            
    37.         //生成签名密钥  
    38.         byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);  
    39.         Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());  
    40.            
    41.           //添加构成JWT的参数  
    42.         JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")  
    43.                                         .claim("role", role)  
    44.                                         .claim("unique_name", name)  
    45.                                         .claim("userid", userId)  
    46.                                         .setIssuer(issuer)  
    47.                                         .setAudience(audience)  
    48.                                         .signWith(signatureAlgorithm, signingKey);  
    49.          //添加Token过期时间  
    50.         if (TTLMillis >= 0) {  
    51.             long expMillis = nowMillis + TTLMillis;  
    52.             Date exp = new Date(expMillis);  
    53.             builder.setExpiration(exp).setNotBefore(now);  
    54.         }  
    55.            
    56.          //生成JWT  
    57.         return builder.compact();  
    58.     }   
    59. }  



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

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.jwt;  
    2.   
    3. public class AccessToken {  
    4.     private String access_token;  
    5.     private String token_type;  
    6.     private long expires_in;  
    7.     public String getAccess_token() {  
    8.         return access_token;  
    9.     }  
    10.     public void setAccess_token(String access_token) {  
    11.         this.access_token = access_token;  
    12.     }  
    13.     public String getToken_type() {  
    14.         return token_type;  
    15.     }  
    16.     public void setToken_type(String token_type) {  
    17.         this.token_type = token_type;  
    18.     }  
    19.     public long getExpires_in() {  
    20.         return expires_in;  
    21.     }  
    22.     public void setExpires_in(long expires_in) {  
    23.         this.expires_in = expires_in;  
    24.     }  
    25. }  

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

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.jwt;  
    2.   
    3. import org.springframework.beans.factory.annotation.Autowired;  
    4. import org.springframework.web.bind.annotation.RequestBody;  
    5. import org.springframework.web.bind.annotation.RequestMapping;  
    6. import org.springframework.web.bind.annotation.RestController;  
    7.   
    8. import com.xiaofangtech.sunt.bean.UserInfo;  
    9. import com.xiaofangtech.sunt.repository.UserInfoRepository;  
    10. import com.xiaofangtech.sunt.utils.MyUtils;  
    11. import com.xiaofangtech.sunt.utils.ResultMsg;  
    12. import com.xiaofangtech.sunt.utils.ResultStatusCode;  
    13.   
    14. @RestController  
    15. public class JsonWebToken {  
    16.     @Autowired  
    17.     private UserInfoRepository userRepositoy;  
    18.       
    19.     @Autowired  
    20.     private Audience audienceEntity;  
    21.       
    22.     @RequestMapping("oauth/token")  
    23.     public Object getAccessToken(@RequestBody LoginPara loginPara)  
    24.     {  
    25.         ResultMsg resultMsg;  
    26.         try  
    27.         {  
    28.             if(loginPara.getClientId() == null   
    29.                     || (loginPara.getClientId().compareTo(audienceEntity.getClientId()) != 0))  
    30.             {  
    31.                 resultMsg = new ResultMsg(ResultStatusCode.INVALID_CLIENTID.getErrcode(),   
    32.                         ResultStatusCode.INVALID_CLIENTID.getErrmsg(), null);  
    33.                 return resultMsg;  
    34.             }  
    35.               
    36.             //验证码校验在后面章节添加  
    37.               
    38.               
    39.             //验证用户名密码  
    40.             UserInfo user = userRepositoy.findUserInfoByName(loginPara.getUserName());  
    41.             if (user == null)  
    42.             {  
    43.                 resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),  
    44.                         ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);  
    45.                 return resultMsg;  
    46.             }  
    47.             else  
    48.             {  
    49.                 String md5Password = MyUtils.getMD5(loginPara.getPassword()+user.getSalt());  
    50.                   
    51.                 if (md5Password.compareTo(user.getPassword()) != 0)  
    52.                 {  
    53.                     resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),  
    54.                             ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);  
    55.                     return resultMsg;  
    56.                 }  
    57.             }  
    58.               
    59.             //拼装accessToken  
    60.             String accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getName()),  
    61.                     user.getRole(), audienceEntity.getClientId(), audienceEntity.getName(),  
    62.                     audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret());  
    63.               
    64.             //返回accessToken  
    65.             AccessToken accessTokenEntity = new AccessToken();  
    66.             accessTokenEntity.setAccess_token(accessToken);  
    67.             accessTokenEntity.setExpires_in(audienceEntity.getExpiresSecond());  
    68.             accessTokenEntity.setToken_type("bearer");  
    69.             resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(),   
    70.                     ResultStatusCode.OK.getErrmsg(), accessTokenEntity);  
    71.             return resultMsg;  
    72.               
    73.         }  
    74.         catch(Exception ex)  
    75.         {  
    76.             resultMsg = new ResultMsg(ResultStatusCode.SYSTEM_ERR.getErrcode(),   
    77.                     ResultStatusCode.SYSTEM_ERR.getErrmsg(), null);  
    78.             return resultMsg;  
    79.         }  
    80.     }  
    81. }  



    6、添加使用jwt认证的filter

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.filter;  
    2.   
    3. import java.io.IOException;  
    4.   
    5. import javax.servlet.Filter;  
    6. import javax.servlet.FilterChain;  
    7. import javax.servlet.FilterConfig;  
    8. import javax.servlet.ServletException;  
    9. import javax.servlet.ServletRequest;  
    10. import javax.servlet.ServletResponse;  
    11. import javax.servlet.http.HttpServletRequest;  
    12. import javax.servlet.http.HttpServletResponse;  
    13.   
    14. import org.springframework.beans.factory.annotation.Autowired;  
    15. import org.springframework.web.context.support.SpringBeanAutowiringSupport;  
    16.   
    17. import com.fasterxml.jackson.databind.ObjectMapper;  
    18. import com.xiaofangtech.sunt.jwt.Audience;  
    19. import com.xiaofangtech.sunt.jwt.JwtHelper;  
    20. import com.xiaofangtech.sunt.utils.ResultMsg;  
    21. import com.xiaofangtech.sunt.utils.ResultStatusCode;  
    22.   
    23. public class HTTPBearerAuthorizeAttribute implements Filter{  
    24.     @Autowired  
    25.     private Audience audienceEntity;  
    26.   
    27.     @Override  
    28.     public void init(FilterConfig filterConfig) throws ServletException {  
    29.         // TODO Auto-generated method stub  
    30.         SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,  
    31.                 filterConfig.getServletContext());  
    32.           
    33.     }  
    34.   
    35.     @Override  
    36.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  
    37.             throws IOException, ServletException {  
    38.         // TODO Auto-generated method stub  
    39.           
    40.         ResultMsg resultMsg;  
    41.         HttpServletRequest httpRequest = (HttpServletRequest)request;  
    42.         String auth = httpRequest.getHeader("Authorization");  
    43.         if ((auth != null) && (auth.length() > 7))  
    44.         {  
    45.             String HeadStr = auth.substring(0, 6).toLowerCase();  
    46.             if (HeadStr.compareTo("bearer") == 0)  
    47.             {  
    48.                   
    49.                 auth = auth.substring(7, auth.length());   
    50.                 if (JwtHelper.parseJWT(auth, audienceEntity.getBase64Secret()) != null)  
    51.                 {  
    52.                     chain.doFilter(request, response);  
    53.                     return;  
    54.                 }  
    55.             }  
    56.         }  
    57.           
    58.         HttpServletResponse httpResponse = (HttpServletResponse) response;  
    59.         httpResponse.setCharacterEncoding("UTF-8");    
    60.         httpResponse.setContentType("application/json; charset=utf-8");   
    61.         httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
    62.   
    63.         ObjectMapper mapper = new ObjectMapper();  
    64.           
    65.         resultMsg = new ResultMsg(ResultStatusCode.INVALID_TOKEN.getErrcode(), ResultStatusCode.INVALID_TOKEN.getErrmsg(), null);  
    66.         httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));  
    67.         return;  
    68.     }  
    69.   
    70.     @Override  
    71.     public void destroy() {  
    72.         // TODO Auto-generated method stub  
    73.           
    74.     }  
    75. }  

    7、在入口处注册filter

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import org.springframework.boot.SpringApplication;  
    7. import org.springframework.boot.autoconfigure.SpringBootApplication;  
    8. import org.springframework.boot.context.embedded.FilterRegistrationBean;  
    9. import org.springframework.boot.context.properties.EnableConfigurationProperties;  
    10. import org.springframework.context.annotation.Bean;  
    11.   
    12. import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute;  
    13. import com.xiaofangtech.sunt.filter.HTTPBearerAuthorizeAttribute;  
    14. import com.xiaofangtech.sunt.jwt.Audience;  
    15.   
    16. @SpringBootApplication  
    17. @EnableConfigurationProperties(Audience.class)  
    18. public class SpringRestApplication {  
    19.   
    20.     public static void main(String[] args) {  
    21.         SpringApplication.run(SpringRestApplication.class, args);  
    22.     }  
    23.       
    24.     @Bean  
    25.     public FilterRegistrationBean  basicFilterRegistrationBean() {  
    26.         FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
    27.         HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute();  
    28.         registrationBean.setFilter(httpBasicFilter);  
    29.         List<String> urlPatterns = new ArrayList<String>();  
    30.         urlPatterns.add("/user/getuser");  
    31.         registrationBean.setUrlPatterns(urlPatterns);  
    32.         return registrationBean;  
    33.     }  
    34.       
    35.     @Bean  
    36.     public FilterRegistrationBean jwtFilterRegistrationBean(){  
    37.         FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
    38.         HTTPBearerAuthorizeAttribute httpBearerFilter = new HTTPBearerAuthorizeAttribute();  
    39.         registrationBean.setFilter(httpBearerFilter);  
    40.         List<String> urlPatterns = new ArrayList<String>();  
    41.         urlPatterns.add("/user/getusers");  
    42.         registrationBean.setUrlPatterns(urlPatterns);  
    43.         return registrationBean;  
    44.     }  
    45. }  


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

    [java] view plain copy
     
    1. package com.xiaofangtech.sunt.utils;  
    2.   
    3. import java.security.MessageDigest;  
    4.   
    5. public class MyUtils {  
    6.     public static String getMD5(String inStr) {  
    7.         MessageDigest md5 = null;  
    8.         try {  
    9.             md5 = MessageDigest.getInstance("MD5");  
    10.         } catch (Exception e) {  
    11.               
    12.             e.printStackTrace();  
    13.             return "";  
    14.         }  
    15.         char[] charArray = inStr.toCharArray();  
    16.         byte[] byteArray = new byte[charArray.length];  
    17.    
    18.         for (int i = 0; i < charArray.length; i++)  
    19.             byteArray[i] = (byte) charArray[i];  
    20.    
    21.         byte[] md5Bytes = md5.digest(byteArray);  
    22.    
    23.         StringBuffer hexValue = new StringBuffer();  
    24.    
    25.         for (int i = 0; i < md5Bytes.length; i++) {  
    26.             int val = ((int) md5Bytes[i]) & 0xff;  
    27.             if (val < 16)  
    28.                 hexValue.append("0");  
    29.             hexValue.append(Integer.toHexString(val));  
    30.         }  
    31.    
    32.         return hexValue.toString();  
    33.     }  
    34. }  

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

    [java] view plain copy
     
    1.        INVALID_CLIENTID(30003, "Invalid clientid"),  
    2. INVALID_PASSWORD(30004, "User name or password is incorrect"),  
    3. INVALID_CAPTCHA(30005, "Invalid captcha or captcha overdue"),  
    4. INVALID_TOKEN(30006, "Invalid token");  



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

    11、代码整体结构

    12、测试

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


        认证通过返回token信息



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

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

        使用正确的token时

  • 相关阅读:
    5.2 TensorFlow:模型的加载,存储,实例
    5.2 TensorFlow:模型的加载,存储,实例
    卷积神经网络(cnn)的体系结构
    卷积神经网络(cnn)的体系结构
    Python学习笔记(四) 函数
    Python学习笔记(三) 字典
    Python学习笔记(二) 字符串
    Python学习笔记(一) 列表和元组
    Linux学习笔记(七) 查询系统
    Linux学习笔记(六) 进程管理
  • 原文地址:https://www.cnblogs.com/pekkle/p/7848085.html
Copyright © 2011-2022 走看看