本文介绍了spring boot实战之filter实现使用jwt进行接口认证,分享给大家
jwt(json web token)
用户发送按照约定,向服务端发送 header、payload 和 signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api
jwt使用流程
本文示例接上面几篇文章中的代码进行编写,请阅读本文的同时可以参考前面几篇文章
1、添加依赖库jjwt,本文中构造jwt及解析jwt都使用了jjwt库
1
2
3
4
5
|
<dependency> <groupid>io.jsonwebtoken</groupid> <artifactid>jjwt</artifactid> <version> 0.6 . 0 </version> </dependency> |
2、添加登录获取token时,所需要的认证信息类loginpara.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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的接口,通过传入用户认证信息(用户名、密码)进行认证获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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、在返回信息类中补充添加错误码
1
2
3
4
|
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时
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://blog.csdn.net/sun_t89/article/details/51923017