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

来源:互联网 发布:python splinter教程 编辑:程序博客网 时间:2024/05/22 00:37


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);}  //生成JWTreturn 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;@RestControllerpublic class JsonWebToken {@Autowiredprivate UserInfoRepository userRepositoy;@Autowiredprivate 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;}}//拼装accessTokenString accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getName()),user.getRole(), audienceEntity.getClientId(), audienceEntity.getName(),audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret());//返回accessTokenAccessToken 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{@Autowiredprivate Audience audienceEntity;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stubSpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,            filterConfig.getServletContext());}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// TODO Auto-generated method stubResultMsg 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;}@Overridepublic 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;    }@Beanpublic 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实战之Filter实现使用JWT进行接口认证

标签:des   class   style   log   com   http   it   si   使用   

原文:http://blog.csdn.net/sun_t89/article/details/51923017

0 0
原创粉丝点击