本文介绍了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