Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_41582038
JustAuth
提交
44bb03d6
J
JustAuth
项目概览
weixin_41582038
/
JustAuth
与 Fork 源项目一致
Fork自
justauth / JustAuth
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JustAuth
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
44bb03d6
编写于
7月 15, 2019
作者:
智布道
👁
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
✨
新增AuthState类,内置默认的state生成规则和校验规则
上级
bfe21229
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
409 addition
and
4 deletion
+409
-4
README.md
README.md
+3
-3
pom.xml
pom.xml
+7
-1
src/main/java/me/zhyd/oauth/utils/AuthState.java
src/main/java/me/zhyd/oauth/utils/AuthState.java
+165
-0
src/test/java/me/zhyd/oauth/utils/AuthStateTest.java
src/test/java/me/zhyd/oauth/utils/AuthStateTest.java
+231
-0
update.md
update.md
+3
-0
未找到文件。
README.md
浏览文件 @
44bb03d6
...
...
@@ -6,7 +6,7 @@
</p>
<p
align=
"center"
>
<a
target=
"_blank"
href=
"https://search.maven.org/search?q=JustAuth"
>
<img
src=
"https://img.shields.io/badge/Maven Central-1.8.
0
-blue.svg"
></img>
<img
src=
"https://img.shields.io/badge/Maven Central-1.8.
1
-blue.svg"
></img>
</a>
<a
target=
"_blank"
href=
"https://gitee.com/yadong.zhang/JustAuth/blob/master/LICENSE"
>
<img
src=
"https://img.shields.io/apm/l/vim-mode.svg?color=yellow"
></img>
...
...
@@ -15,7 +15,7 @@
<img
src=
"https://img.shields.io/badge/JDK-1.8+-green.svg"
></img>
</a>
<a
target=
"_blank"
href=
"https://apidoc.gitee.com/yadong.zhang/JustAuth/"
>
<img
src=
"https://img.shields.io/badge/Docs-1.8.
0
-orange.svg"
></img>
<img
src=
"https://img.shields.io/badge/Docs-1.8.
1
-orange.svg"
></img>
</a>
</p>
...
...
@@ -68,7 +68,7 @@ JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具
<dependency>
<groupId>
me.zhyd.oauth
</groupId>
<artifactId>
JustAuth
</artifactId>
<version>
1.8.
0
</version>
<version>
1.8.
1
</version>
</dependency>
```
-
调用api
...
...
pom.xml
浏览文件 @
44bb03d6
...
...
@@ -6,7 +6,7 @@
<groupId>
me.zhyd.oauth
</groupId>
<artifactId>
JustAuth
</artifactId>
<version>
1.8.
0
</version>
<version>
1.8.
1
</version>
<name>
JustAuth
</name>
<url>
https://gitee.com/yadong.zhang/JustAuth
</url>
...
...
@@ -54,6 +54,7 @@
<junit-version>
4.11
</junit-version>
<fastjson-version>
1.2.44
</fastjson-version>
<alipay-sdk-version>
3.7.4.ALL
</alipay-sdk-version>
<slf4j-version>
1.7.25
</slf4j-version>
</properties>
<dependencies>
...
...
@@ -84,6 +85,11 @@
<version>
${alipay-sdk-version}
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-simple
</artifactId>
<version>
${slf4j-version}
</version>
</dependency>
</dependencies>
<build>
...
...
src/main/java/me/zhyd/oauth/utils/AuthState.java
0 → 100644
浏览文件 @
44bb03d6
package
me.zhyd.oauth.utils
;
import
cn.hutool.core.codec.Base64
;
import
cn.hutool.core.util.RandomUtil
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
me.zhyd.oauth.exception.AuthException
;
import
me.zhyd.oauth.request.ResponseStatus
;
import
java.nio.charset.Charset
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* state工具,负责创建、获取和删除state
*
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 1.0
* @since 1.8
*/
@Slf4j
public
class
AuthState
{
/**
* 空字符串
*/
private
static
final
String
EMPTY_STR
=
""
;
/**
* state存储器
*/
private
static
ConcurrentHashMap
<
String
,
String
>
stateBucket
=
new
ConcurrentHashMap
<>();
/**
* 生成随机的state
*
* @param source oauth平台
* @return state
*/
public
static
String
create
(
String
source
)
{
return
create
(
source
,
RandomUtil
.
randomString
(
4
));
}
/**
* 创建state
*
* @param source oauth平台
* @param body 希望加密到state的消息体
* @return state
*/
public
static
String
create
(
String
source
,
Object
body
)
{
return
create
(
source
,
JSON
.
toJSONString
(
body
));
}
/**
* 创建state
* state建议格式请参考:https://gitee.com/yadong.zhang/JustAuth/wikis/Q&A?sort_id=1513074#3-%E5%8D%87%E7%BA%A7%E5%88%B0180%E5%90%8E%E5%AF%B9%E4%BA%8Estate%E5%8F%82%E6%95%B0%E6%9C%89%E4%BB%80%E4%B9%88%E7%89%B9%E6%AE%8A%E8%A6%81%E6%B1%82%E5%90%97
*
* @param source oauth平台
* @param body 希望加密到state的消息体
* @return state
*/
public
static
String
create
(
String
source
,
String
body
)
{
String
currentIp
=
getCurrentIp
();
String
simpleKey
=
((
source
+
currentIp
));
String
key
=
Base64
.
encode
(
simpleKey
.
getBytes
(
Charset
.
forName
(
"UTF-8"
)));
log
.
debug
(
"Create the state: ip={}, platform={}, simpleKey={}, key={}, body={}"
,
currentIp
,
source
,
simpleKey
,
key
,
body
);
if
(
stateBucket
.
containsKey
(
key
))
{
log
.
debug
(
"Get from bucket: {}"
,
stateBucket
.
get
(
key
));
return
stateBucket
.
get
(
key
);
}
String
simpleState
=
source
+
"_"
+
currentIp
+
"_"
+
body
;
String
state
=
Base64
.
encode
(
simpleState
.
getBytes
(
Charset
.
forName
(
"UTF-8"
)));
log
.
debug
(
"Create a new state: {}"
,
state
,
simpleState
);
stateBucket
.
put
(
key
,
state
);
return
state
;
}
/**
* 获取state
*
* @param source oauth平台
* @return state
*/
public
static
String
get
(
String
source
)
{
String
currentIp
=
getCurrentIp
();
String
simpleKey
=
((
source
+
currentIp
));
String
key
=
Base64
.
encode
(
simpleKey
.
getBytes
(
Charset
.
forName
(
"UTF-8"
)));
log
.
debug
(
"Get state by the key[{}], current ip[{}]"
,
key
,
currentIp
);
return
stateBucket
.
get
(
key
);
}
/**
* 获取state中保存的body内容
*
* @param source oauth平台
* @param state 加密后的state
* @param clazz body的实际类型
* @return state
*/
public
static
<
T
>
T
getBody
(
String
source
,
String
state
,
Class
<
T
>
clazz
)
{
if
(
StringUtils
.
isEmpty
(
state
)
||
null
==
clazz
)
{
return
null
;
}
log
.
debug
(
"Get body from the state[{}] of the {} and convert it to {}"
,
state
,
source
,
clazz
.
toString
());
String
currentIp
=
getCurrentIp
();
String
decodedState
=
Base64
.
decodeStr
(
state
);
log
.
debug
(
"The decoded state is [{}]"
,
decodedState
);
if
(!
decodedState
.
startsWith
(
source
))
{
return
null
;
}
String
noneSourceState
=
decodedState
.
substring
(
source
.
length
()
+
1
);
if
(!
noneSourceState
.
startsWith
(
currentIp
))
{
// ip不相同,可能为非法的请求
throw
new
AuthException
(
ResponseStatus
.
ILLEGAL_REQUEST
);
}
String
body
=
noneSourceState
.
substring
(
currentIp
.
length
()
+
1
);
log
.
debug
(
"body is [{}]"
,
body
);
if
(
clazz
==
String
.
class
)
{
return
(
T
)
body
;
}
if
(
clazz
==
Integer
.
class
)
{
return
(
T
)
Integer
.
valueOf
(
Integer
.
parseInt
(
body
));
}
if
(
clazz
==
Long
.
class
)
{
return
(
T
)
Long
.
valueOf
(
Long
.
parseLong
(
body
));
}
if
(
clazz
==
Short
.
class
)
{
return
(
T
)
Short
.
valueOf
(
Short
.
parseShort
(
body
));
}
if
(
clazz
==
Double
.
class
)
{
return
(
T
)
Double
.
valueOf
(
Double
.
parseDouble
(
body
));
}
if
(
clazz
==
Float
.
class
)
{
return
(
T
)
Float
.
valueOf
(
Float
.
parseFloat
(
body
));
}
if
(
clazz
==
Boolean
.
class
)
{
return
(
T
)
Boolean
.
valueOf
(
Boolean
.
parseBoolean
(
body
));
}
if
(
clazz
==
Byte
.
class
)
{
return
(
T
)
Byte
.
valueOf
(
Byte
.
parseByte
(
body
));
}
return
JSON
.
parseObject
(
body
,
clazz
);
}
/**
* 登录成功后,清除state
*
* @param source oauth平台
*/
public
static
void
delete
(
String
source
)
{
String
currentIp
=
getCurrentIp
();
String
simpleKey
=
((
source
+
currentIp
));
String
key
=
Base64
.
encode
(
simpleKey
.
getBytes
(
Charset
.
forName
(
"UTF-8"
)));
log
.
debug
(
"Delete used state[{}] by the key[{}], current ip[{}]"
,
stateBucket
.
get
(
key
),
key
,
currentIp
);
stateBucket
.
remove
(
key
);
}
private
static
String
getCurrentIp
()
{
String
currentIp
=
IpUtils
.
getIp
();
return
StringUtils
.
isEmpty
(
currentIp
)
?
EMPTY_STR
:
currentIp
;
}
}
src/test/java/me/zhyd/oauth/utils/AuthStateTest.java
0 → 100644
浏览文件 @
44bb03d6
package
me.zhyd.oauth.utils
;
import
cn.hutool.core.date.DatePattern
;
import
cn.hutool.core.date.DateUtil
;
import
me.zhyd.oauth.config.AuthConfig
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
java.util.*
;
public
class
AuthStateTest
{
/**
* step1 生成state: 预期创建一个新的state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9yM3ll
*
* step2 重复生成state: 预期从bucket中返回一个可用的state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9yM3ll
*
* step3 获取state: 预期获取上面生成的state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9yM3ll
*
* step4 删除state: 预期删除掉上面创建的state...
*
* step5 重新获取state: 预期返回null...
* null
*/
@Test
public
void
test
()
{
String
source
=
"github"
;
System
.
out
.
println
(
"\nstep1 生成state: 预期创建一个新的state..."
);
String
state
=
AuthState
.
create
(
source
);
System
.
out
.
println
(
state
);
System
.
out
.
println
(
"\nstep2 重复生成state: 预期从bucket中返回一个可用的state..."
);
String
recreateState
=
AuthState
.
create
(
source
);
System
.
out
.
println
(
recreateState
);
Assert
.
assertEquals
(
state
,
recreateState
);
System
.
out
.
println
(
"\nstep3 获取state: 预期获取上面生成的state..."
);
String
stateByBucket
=
AuthState
.
get
(
source
);
System
.
out
.
println
(
stateByBucket
);
Assert
.
assertEquals
(
state
,
stateByBucket
);
System
.
out
.
println
(
"\nstep4 删除state: 预期删除掉上面创建的state..."
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\nstep5 重新获取state: 预期返回null..."
);
String
deletedState
=
AuthState
.
get
(
source
);
System
.
out
.
println
(
deletedState
);
Assert
.
assertNull
(
deletedState
);
}
/**
* 通过随机字符串生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9wdnAy
*
* 通过传入自定义的字符串生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV/ov5nmmK/kuIDkuKrlrZfnrKbkuLI=
*
* 通过传入数字生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV8xMTE=
*
* 通过传入日期生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV8xNTQ2MzE1OTMyMDAw
*
* 通过传入map生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV97InVzZXJUb2tlbiI6Inh4eHh4IiwidXNlcklkIjoxfQ==
*
* 通过传入List生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9bInh4eHgiLCJ4eHh4eHh4eCJd
*
* 通过传入实体类生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV97ImNsaWVudElkIjoieHh4eHgiLCJjbGllbnRTZWNyZXQiOiJ4eHh4eCIsInVuaW9uSWQiOmZhbHNlfQ==
*/
@Test
public
void
create
()
{
String
source
=
"github"
;
System
.
out
.
println
(
"\n通过随机字符串生成state..."
);
String
state
=
AuthState
.
create
(
source
);
System
.
out
.
println
(
state
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入自定义的字符串生成state..."
);
String
stringBody
=
"这是一个字符串"
;
String
stringState
=
AuthState
.
create
(
source
,
stringBody
);
System
.
out
.
println
(
stringState
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入数字生成state..."
);
Integer
numberBody
=
111
;
String
numberState
=
AuthState
.
create
(
source
,
numberBody
);
System
.
out
.
println
(
numberState
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入日期生成state..."
);
Date
dateBody
=
DateUtil
.
parse
(
"2019-01-01 12:12:12"
,
DatePattern
.
NORM_DATETIME_PATTERN
);
String
dateState
=
AuthState
.
create
(
source
,
dateBody
);
System
.
out
.
println
(
dateState
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入map生成state..."
);
Map
<
String
,
Object
>
mapBody
=
new
HashMap
<>();
mapBody
.
put
(
"userId"
,
1
);
mapBody
.
put
(
"userToken"
,
"xxxxx"
);
String
mapState
=
AuthState
.
create
(
source
,
mapBody
);
System
.
out
.
println
(
mapState
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入List生成state..."
);
List
<
String
>
listBody
=
new
ArrayList
<>();
listBody
.
add
(
"xxxx"
);
listBody
.
add
(
"xxxxxxxx"
);
String
listState
=
AuthState
.
create
(
source
,
listBody
);
System
.
out
.
println
(
listState
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入实体类生成state..."
);
AuthConfig
entityBody
=
AuthConfig
.
builder
()
.
clientId
(
"xxxxx"
)
.
clientSecret
(
"xxxxx"
)
.
build
();
String
entityState
=
AuthState
.
create
(
source
,
entityBody
);
System
.
out
.
println
(
entityState
);
AuthState
.
delete
(
source
);
}
/**
* 通过随机字符串生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9kaWNn
* dicg
*
* 通过传入自定义的字符串生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV/ov5nmmK/kuIDkuKrlrZfnrKbkuLI=
* 这是一个字符串
*
* 通过传入数字生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV8xMTE=
* 111
*
* 通过传入日期生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV8xNTQ2MzE1OTMyMDAw
* Tue Jan 01 12:12:12 CST 2019
*
* 通过传入map生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV97InVzZXJUb2tlbiI6Inh4eHh4IiwidXNlcklkIjoxfQ==
* {userToken=xxxxx, userId=1}
*
* 通过传入List生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV9bInh4eHgiLCJ4eHh4eHh4eCJd
* [xxxx, xxxxxxxx]
*
* 通过传入实体类生成state...
* Z2l0aHViXzE5Mi4xNjguMTkuMV97ImNsaWVudElkIjoieHh4eHgiLCJjbGllbnRTZWNyZXQiOiJ4eHh4eCIsInVuaW9uSWQiOmZhbHNlfQ==
* me.zhyd.oauth.config.AuthConfig@725bef66
*/
@Test
public
void
getBody
()
{
String
source
=
"github"
;
System
.
out
.
println
(
"\n通过随机字符串生成state..."
);
String
state
=
AuthState
.
create
(
source
);
System
.
out
.
println
(
state
);
String
body
=
AuthState
.
getBody
(
source
,
state
,
String
.
class
);
System
.
out
.
println
(
body
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入自定义的字符串生成state..."
);
String
stringBody
=
"这是一个字符串"
;
String
stringState
=
AuthState
.
create
(
source
,
stringBody
);
System
.
out
.
println
(
stringState
);
stringBody
=
AuthState
.
getBody
(
source
,
stringState
,
String
.
class
);
System
.
out
.
println
(
stringBody
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入数字生成state..."
);
Integer
numberBody
=
111
;
String
numberState
=
AuthState
.
create
(
source
,
numberBody
);
System
.
out
.
println
(
numberState
);
numberBody
=
AuthState
.
getBody
(
source
,
numberState
,
Integer
.
class
);
System
.
out
.
println
(
numberBody
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入日期生成state..."
);
Date
dateBody
=
DateUtil
.
parse
(
"2019-01-01 12:12:12"
,
DatePattern
.
NORM_DATETIME_PATTERN
);
String
dateState
=
AuthState
.
create
(
source
,
dateBody
);
System
.
out
.
println
(
dateState
);
dateBody
=
AuthState
.
getBody
(
source
,
dateState
,
Date
.
class
);
System
.
out
.
println
(
dateBody
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入map生成state..."
);
Map
<
String
,
Object
>
mapBody
=
new
HashMap
<>();
mapBody
.
put
(
"userId"
,
1
);
mapBody
.
put
(
"userToken"
,
"xxxxx"
);
String
mapState
=
AuthState
.
create
(
source
,
mapBody
);
System
.
out
.
println
(
mapState
);
mapBody
=
AuthState
.
getBody
(
source
,
mapState
,
Map
.
class
);
System
.
out
.
println
(
mapBody
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入List生成state..."
);
List
<
String
>
listBody
=
new
ArrayList
<>();
listBody
.
add
(
"xxxx"
);
listBody
.
add
(
"xxxxxxxx"
);
String
listState
=
AuthState
.
create
(
source
,
listBody
);
System
.
out
.
println
(
listState
);
listBody
=
AuthState
.
getBody
(
source
,
listState
,
List
.
class
);
System
.
out
.
println
(
listBody
);
AuthState
.
delete
(
source
);
System
.
out
.
println
(
"\n通过传入实体类生成state..."
);
AuthConfig
entityBody
=
AuthConfig
.
builder
()
.
clientId
(
"xxxxx"
)
.
clientSecret
(
"xxxxx"
)
.
build
();
String
entityState
=
AuthState
.
create
(
source
,
entityBody
);
System
.
out
.
println
(
entityState
);
entityBody
=
AuthState
.
getBody
(
source
,
entityState
,
AuthConfig
.
class
);
System
.
out
.
println
(
entityBody
);
AuthState
.
delete
(
source
);
}
@Test
public
void
getErrorStateBody
()
{
String
source
=
"github"
;
String
state
=
"1111111111111111111111111111111"
;
String
body
=
AuthState
.
getBody
(
source
,
state
,
String
.
class
);
System
.
out
.
println
(
body
);
AuthState
.
delete
(
source
);
}
}
\ No newline at end of file
update.md
浏览文件 @
44bb03d6
### 2019/07/15
1.
新增
`AuthState`
类,内置默认的state生成规则和校验规则
### 2019/07/12
1.
合并
[
Braavos96
](
https://github.com/Braavos96
)
提交的
[
PR#16
](
https://github.com/zhangyd-c/JustAuth/pull/16
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录