Spring Cloud与微服务学习总结(5)——认证鉴权与API权限控制在微服务架构中的设计与实现(三)
本文转载自( http://blueskykong.com/2017/10/24/security3/)
1. 前文回顾
在开始讲解这一篇文章之前,先对之前两篇文章进行回忆下。在第一篇 认证鉴权与API权限控制在微服务架构中的设计与实现(一)介绍了该项目的背景以及技术调研与最后选型。第二篇认证鉴权与API权限控制在微服务架构中的设计与实现(二)画出了简要的登录和校验的流程图,并重点讲解了用户身份的认证与token发放的具体实现。
身份及API权限校验的流程图
本文重点讲解鉴权,包括两个方面:token合法性以及API级别的操作权限。首先token合法性很容易理解,第二篇文章讲解了获取授权token的一系列流程,token是否是认证服务器颁发的,必然是需要验证的。其次对于API级别的操作权限,将上下文信息不具备操作权限的请求直接拒绝,当然此处是设计token合法性校验在先,其次再对操作权限进行验证,如果前一个验证直接拒绝,通过则进入操作权限验证。
2.资源服务器配置
ResourceServer
配置在第一篇就列出了,在进入鉴权之前,把这边的配置搞清,即使有些配置在本项目中没有用到,大家在自己的项目有可能用到。
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
|
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
//http安全配置
@Override
public void configure(HttpSecurity http) throws Exception {
//禁掉csrf,设置session策略
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()//默认允许访问
.requestMatchers().antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().logout() //logout注销端点配置
.logoutUrl("/logout")
.clearAuthentication(true)
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.addLogoutHandler(customLogoutHandler());
}
//添加自定义的CustomLogoutHandler
@Bean
public CustomLogoutHandler customLogoutHandler() {
return new CustomLogoutHandler();
}
//资源安全配置相关
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
super.configure(resources);
}
}
|
(3).关联的ResourceServerSecurityConfigurer
,为资源服务器添加特殊的配置,默认的适用于很多应用,但是这边的修改至少以resourceId为单位。类图如下。
ResourceServerSecurityConfigurer类图
3. 鉴权endpoint
鉴权主要是使用内置的endpoint /oauth/check_token
,笔者将对端点的分析放在前面,因为这是鉴权的唯一入口。下面我们来看下该API接口中的主要代码。
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
|
@RequestMapping(value = "/oauth/check_token")
@ResponseBody
public Map<String, ?> checkToken(CheckTokenEntity checkTokenEntity) {
//CheckTokenEntity为自定义的dto
Assert.notNull(checkTokenEntity, "invalid token entity!");
//识别token
OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(checkTokenEntity.getToken());
//判断token是否为空
if (token == null) {
throw new InvalidTokenException("Token was not recognised");
}
//未过期
if (token.isExpired()) {
throw new InvalidTokenException("Token has expired");
}
//加载OAuth2Authentication
OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());
//获取response,token合法性验证完毕
Map<String, Object> response = (Map<String, Object>) accessTokenConverter.convertAccessToken(token, authentication);
//check for api permission
if (response.containsKey("jti")) {
//上下文操作权限校验
Assert.isTrue(checkPermissions.checkPermission(checkTokenEntity));
}
response.put("active", true); // Always true if token exists and not expired
return response;
}
|
4. 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
|
public class JdbcTokenStore implements TokenStore {
...
public OAuth2AccessToken readAccessToken(String tokenValue) {
OAuth2AccessToken accessToken = null;
try {
//使用selectAccessTokenSql语句,调用了私有的extractTokenKey()方法
accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAccessToken(rs.getBytes(2));
}
}, extractTokenKey(tokenValue));
}
//异常情况
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + tokenValue);
}
}
catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize access token for " + tokenValue, e);
//不合法则移除
removeAccessToken(tokenValue);
}
return accessToken;
}
...
//提取TokenKey方法
protected String extractTokenKey(String value) {
if (value == null) {
return null;
}
MessageDigest digest;
try {
//MD5
digest = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
byte[] bytes = digest.digest(value.getBytes("UTF-8"));
return String.format("%032x", new BigInteger(1, bytes));
}
catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
}
}
|
5. API级别权限校验
1
2
|
http.authorizeRequests()
.antMatchers("/order/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@Component
public class CustomCheckPermission implements CheckPermissions {
@Autowired
private PermissionService permissionService;
@Override
public boolean checkPermission(CheckTokenEntity checkTokenEntity) {
String url = checkTokenEntity.getUri();
Long affairId = checkTokenEntity.getAffairId();
Long roleId = checkTokenEntity.getRoleId();
//校验
if (StringUtils.isEmpty(url) || affairId <= 0 || roleId <= 0) {
return true;
} else {
return permissionService.checkPermission(url, affairId, roleId);
}
}
}
|
6. 总结
Spring Cloud与微服务学习总结(5)——认证鉴权与API权限控制在微服务架构中的设计与实现(三)相关推荐
- Spring Cloud与微服务学习总结(6)——认证鉴权与API权限控制在微服务架构中的设计与实现(四)
本文转载自(http://blueskykong.com/2017/10/26/security4/) 1. 前文回顾 首先还是照例对前文进行回顾.在第一篇 认证鉴权与API权限控制在微服务架构中的设 ...
- Spring Cloud与微服务学习总结(3)——认证鉴权与API权限控制在微服务架构中的设计与实现(一)
本文转载自(http://blueskykong.com/2017/10/19/security1/) 1. 背景 最近在做权限相关服务的开发,在系统微服务化后,原有的单体应用是基于session的安 ...
- Spring Cloud与微服务学习总结(4)——认证鉴权与API权限控制在微服务架构中的设计与实现(二)
本文转载自(http://blueskykong.com/2017/10/19/security2/) 1. 系统概览 在上一篇 认证鉴权与API权限控制在微服务架构中的设计与实现(一)介绍了该项目的 ...
- 认证鉴权与API权限控制在微服务架构中的设计与实现(一)
作者: [Aoho's Blog] 引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现. 1. ...
- 认证鉴权与API权限控制在微服务架构中的设计与实现
引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现. 1. 背景 最近在做权限相关服务的开发, ...
- api postmain 鉴权_认证鉴权与API权限控制在微服务架构中的设计与实现(一)
引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现. 1. 背景 最近在做权限相关服务的开发, ...
- spring cloud Alibaba 的 Nacos学习笔记
spring cloud Alibaba 的 Nacos学习笔记 文章目录 spring cloud Alibaba 的 Nacos学习笔记 下载nacos spring cloud Alibaba依 ...
- No6-6.从零搭建spring-cloud-alibaba微服务框架,添加用户鉴权逻辑,动态数据权限(使用AOP实现)等(六,no6-6)
代码地址与接口看总目录:[学习笔记]记录冷冷-pig项目的学习过程,大概包括Authorization Server.springcloud.Mybatis Plus~~~_清晨敲代码的博客-CSDN ...
- 快速搭建一个网关服务,动态路由、鉴权看完就会(含流程图)
[文章来源]https://sourl.cn/tcbSPi 前 言 本文记录一下我是如何使用Gateway搭建网关服务及实现动态路由的,帮助大家学习如何快速搭建一个网关服务,了解路由相关配置,鉴权的流 ...
最新文章
- Latex中的插入表格
- 恭喜CocoStudio 1.5和Mac版本发布
- Java序列化闲聊:序列化和Json
- java项目性能测试过程记录
- MySQL使用命令备份和还原数据库
- Java实现斐波那契数列Fibonacci
- 光端机各种类型的接口介绍
- mysql as tmp,启动mysql时显示:/tmp/mysql.sock 不存在的解决办法
- [Leetcode][第5458题][JAVA][字符串的好分割数目][双指针][HashSet]
- android webview 重定向 多次load问题,关于WebView 重定向行为导致的多次加载的问题...
- JAVA加密或混淆技术总结
- 嵌入式文件系统固件img制作与解包
- QQ音乐的歌曲真实地址解析
- HLS调用vitis库
- MIPI摄像头工程=7系列FPGA + OV5640(MIPI) + 15 分钟 + VITIS
- android加密、签名相关
- 【Python】文件夹的基本操作
- Centos系统mysql 忘记root用户的密码
- 简述Java长期占据主要地位的原因
- 用好这两个键,你就是电脑高手啦
热门文章
- 树莓派c语言实现modbus主机_特斯拉+树莓派实现车牌识别检测系统
- java trim all,[JAVA中各种去除空格][java string.trim()][str.replaceAll去空格]
- 继承的原理java_Java继承和多态的原理
- python散点图密度颜色_Python实现彩色散点图绘制(利用色带对散点图进行颜色渲染)...
- android仿bilibili ui,android指纹识别、拼图游戏、仿MIUI长截屏、bilibili最美创意等源码...
- vue cli脚手架详解_vue-cli脚手架搭建vue项目搭建
- lssvm回归 matlab,lssvm回归预测的程序运行不了 求高手修改指点
- finally 嵌套_学习 Rust【2】减少代码嵌套
- java scan hbase_hbase+java实例,Scan查询所有、get根据rowkey查询一行或一列数据
- jssdk 保存文件到手机_手机混用闪存到底是真是假?教你查手机闪存型号