詳解Spring Boot實戰(zhàn)之Filter實現(xiàn)使用JWT進行接口認(rèn)證
本文介紹了spring Boot實戰(zhàn)之Filter實現(xiàn)使用JWT進行接口認(rèn)證,分享給大家
jwt(json web token)
用戶發(fā)送按照約定,向服務(wù)端發(fā)送 Header、Payload 和 Signature,并包含認(rèn)證信息(密碼),驗證通過后服務(wù)端返回一個token,之后用戶使用該token作為登錄憑證,適合于移動端和api
jwt使用流程

本文示例接上面幾篇文章中的代碼進行編寫,請閱讀本文的同時可以參考前面幾篇文章
1、添加依賴庫jjwt,本文中構(gòu)造jwt及解析jwt都使用了jjwt庫
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.6.0</version> </dependency>
2、添加登錄獲取token時,所需要的認(rèn)證信息類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、添加構(gòu)造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());
//添加構(gòu)成JWT的參數(shù)
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返回結(jié)果類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的接口,通過傳入用戶認(rèn)證信息(用戶名、密碼)進行認(rèn)證獲取
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;
}
//驗證碼校驗在后面章節(jié)添加
//驗證用戶名密碼
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認(rèn)證的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類,在上一篇文章中定義,本文不再重復(fù)說明
11、代碼整體結(jié)構(gòu)

12、測試
1) 獲取token,傳入用戶認(rèn)證信息

認(rèn)證通過返回token信息

2) 使用上面獲取的token進行接口調(diào)用
未使用token,獲取token錯誤,或者token過期時

使用正確的token時

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue+Jwt+SpringBoot+Ldap完成登錄認(rèn)證的示例代碼
- Springboot集成Spring Security實現(xiàn)JWT認(rèn)證的步驟詳解
- SpringBoot整合SpringSecurity和JWT和Redis實現(xiàn)統(tǒng)一鑒權(quán)認(rèn)證
- SpringBoot使用Jwt處理跨域認(rèn)證問題的教程詳解
- 詳解SpringBoot如何使用JWT實現(xiàn)身份認(rèn)證和授權(quán)
- 利用Springboot實現(xiàn)Jwt認(rèn)證的示例代碼
- springboot+jwt實現(xiàn)token登陸權(quán)限認(rèn)證的實現(xiàn)
- SpringBoot整合SpringSecurity實現(xiàn)JWT認(rèn)證的項目實踐
- Spring Boot整合JWT實現(xiàn)認(rèn)證與授權(quán)的項目實踐
相關(guān)文章
Mybatis-Plus自動填充更新操作相關(guān)字段的實現(xiàn)
這篇文章主要介紹了Mybatis-Plus自動填充更新操作相關(guān)字段的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
詳解OpenCV For Java環(huán)境搭建與功能演示
這篇文章主要介紹了x詳解OpenCV For Java環(huán)境搭建與功能演示,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
java springmvc 注冊中央調(diào)度器代碼解析
這篇文章主要介紹了java springmvc 注冊中央調(diào)度器代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08

