我们知道OAuth2的官方提供了四种令牌的获取,简化模式,授权码模式,密码模式,客户端模式。其中密码模式中仅仅支持我们通过用户名和密码的方式获取令牌,那么我们如何去实现一个我们自己的令牌获取的模式呢?下面我们将以用户名,密码,角色三个信息的方式来获取令牌。
在授权模式中,授权模式的核心接口是 TokenGranter ,他拥有一个抽象实现类 AbstractTokenGranter ,我们需要自定义新的 grant type ,就再写一个他的子类即可,如下:
public class AccountRoleTokenGranter extends AbstractTokenGranter {
private static final String GRANT_TYPE = "password_role";
// 获取用户信息的实现
private UserRoleDetailServiceImpl userRoleDetailService;
/**
* 构造方法提供一些必要的注入的参数
* 通过这些参数来完成我们父类的构建
*
* @param tokenServices tokenServices
* @param clientDetailsService clientDetailsService
* @param oAuth2RequestFactory oAuth2RequestFactory
* @param userRoleDetailService userDetailsService
*/
public AccountRoleTokenGranter(AuthorizationServerTokenServices tokenServices,
ClientDetailsService clientDetailsService,
OAuth2RequestFactory oAuth2RequestFactory,
UserRoleDetailServiceImpl userRoleDetailService) {
super(tokenServices, clientDetailsService, oAuth2RequestFactory, GRANT_TYPE);
this.userRoleDetailService = userRoleDetailService;
}
/**
* 在这里查询我们用户,构建用户的授权信息
*
* @param client 客户端
* @param tokenRequest tokenRequest
* @return OAuth2Authentication
*/
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> params = tokenRequest.getRequestParameters();
String account = params.getOrDefault("username", "");
String role = params.getOrDefault("role", "");
// 获取用户信息
UserDetails userDetails = userRoleDetailService.loadUserByAccountAndRole(account, role);
if (ObjectUtil.isNull(userDetails)) {
throw new UsernameNotFoundException("用户角色不存在");
}
// 构建用户授权信息
Authentication user = new AccountRoleAuthenticationToken(userDetails.getUsername(),
userDetails.getPassword(), userDetails.getAuthorities());
return new OAuth2Authentication(tokenRequest.createOAuth2Request(client), user);
}
}
配置用户信息获取实现类UserRoleDetailServiceImpl
@Service
public class UserRoleDetailServiceImpl {
private UserService userService;
private RoleService roleService;
@Autowired
public UserRoleDetailServiceImpl(UserService userService, RoleService roleService) {
this.userService = userService;
this.roleService = roleService;
}
public UserCredential loadUserByAccountAndRole(String account, String roles) throws UsernameNotFoundException {
// 查询相应用户
UserDetailDTO userCredential = userService.findByAccountAndRole(account, roles);
if (ObjectUtils.isEmpty(userCredential)) {
throw new UsernameNotFoundException("该账号角色不存在!");
}
Set<GrantedAuthority> grantedAuthorities = Sets.newHashSet();
List<Role> roleResult = userService.findRoleByUserId(Integer.valueOf(userCredential.getUserId()));
if (!roleResult.isEmpty()) {
for (Role role : roleResult) {
if (StrUtil.equalsIgnoreCase(role.getRoleName(), roles)) {
//角色必须是ROLE_开头,可以在数据库中设置
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleName());
grantedAuthorities.add(grantedAuthority);
//获取权限
List<MenuDTO> menuByRoleId = roleService.findMenuByRoleId(role.getRoleId());
if (!menuByRoleId.isEmpty()) {
for (MenuDTO menu : menuByRoleId) {
if (StringUtils.isNotBlank(menu.getPerms())) {
GrantedAuthority authority = new SimpleGrantedAuthority(menu.getPerms());
grantedAuthorities.add(authority);
}
}
}
}
}
}
UserCredential authUser = new UserCredential(account, userCredential.getPassword(), grantedAuthorities);
BeanUtils.copyProperties(userCredential, authUser);
return authUser;
}
}
/**
* 认证用户信息类
*
* @author zhongyj <1126834403@qq.com><br/>
* @date 2020/2/25
*/
@Setter
@Getter
public class UserCredential extends User implements Serializable {
private static final long serialVersionUID = 2554837818190360741L;
public static final String DEFAULT_USER = "dimples";
private boolean accountNonExpired = true;
private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true;
private boolean enabled = true;
private Integer userId;
private String userCode;
private String account;
private String username;
private String status;
private Date createDate;
private Date modifyDate;
public UserCredential(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
this.account = username;
}
public UserCredential(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
接下来就只需将其添加到Oauth2AuthorizationServerConfig 中
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
// 配置token存储源
.tokenStore(tokenStore())
// 配置权限管理
.authenticationManager(authenticationManager);
endpoints.tokenGranter(tokenGranter(endpoints));
}
/**
* 重点
* 先获取已经有的五种授权,然后添加我们自己的进去
*
* @param endpoints AuthorizationServerEndpointsConfigurer
* @return TokenGranter
*/
private TokenGranter tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints) {
List<TokenGranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
granters.add(new AccountRoleTokenGranter(
endpoints.getTokenServices(),
endpoints.getClientDetailsService(),
endpoints.getOAuth2RequestFactory(),
userRoleDetailService));
return new CompositeTokenGranter(granters);
}
参考资料:
OAuth + Security - 6 - 自定义授权模式的更多相关文章
-
Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战
一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...
-
IdentityServer4 自定义授权模式
IdentityServer4除了提供常规的几种授权模式外(AuthorizationCode.ClientCredentials.Password.RefreshToken.DeviceCode), ...
-
Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...
-
转 - spring security oauth2 password授权模式
原贴地址: https://segmentfault.com/a/1190000012260914#articleHeader6 序 前面的一篇文章讲了spring security oauth2的c ...
-
IdentityServer4 实现自定义 GrantType 授权模式
OAuth 2.0 默认四种授权模式(GrantType): 授权码模式(authorization_code) 简化模式(implicit) 密码模式(password) 客户端模式(client_ ...
-
【.NET Core项目实战-统一认证平台】第十四章 授权篇-自定义授权方式
[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何强制令牌过期的实现,相信大家对IdentityServer4的验证流程有了更深的了解,本篇我将介绍如何使用自定义的授权方 ...
-
Spring Security OAuth2 Demo —— 隐式授权模式(Implicit)
本文可以转载,但请注明出处https://www.cnblogs.com/hellxz/p/oauth2_impilit_pattern.html 写在前面 在文章OAuth 2.0 概念及授权流程梳 ...
-
Spring Security如何优雅的增加OAuth2协议授权模式
一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...
-
SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...
随机推荐
-
php-001-win7 环境下 wamp 的至简部署
此文主要记录学习 PHP 开发环境 wamp 的至简部署.敬请各位小主参阅,若有不足之处,敬请大神指正,不胜感激! 首先依据自身的操作系统选择,进入 wamp 的网站 :http://www.wamp ...
-
adb不响应
1.CMD命令窗口输入:adb nodaemon server .然后就会提示你哪个端口被占用了. 2.输入netstat -ano | findstr "5037" .然后会弹出 ...
-
jQuery中的ready方法及实现按需加载css,js
模拟jQuery中的ready方法及实现按需加载css,js 一.ready函数的实现 经常用jQuery类库或其他类库中的ready方法,有时候想想它们到底是怎么实现的,但是看了一下jQuery中的 ...
-
排列组合python
python 的 itertools模块 可以专业的处理的排列组合问题 写在自己博客里,怕下次找不到喽
-
外部引入的js 判断js脚本加载是否完成,完成后执行 相应的动作(以引入百度地图js为例)
可以使用JQuery的 $.getScript(url,function(){});方法 $.getScript("http://api.map.baidu.com/getscript?v= ...
-
20175317 《Java程序设计》第二周学习总结
20175317 <Java程序设计>第二周学习总结 教材学习内容总结 第二周我学习了教材三四章的内容,了解了Java与C语言的相似与不同之处. 其中第二章学到了标识符与关键字.基本数据类 ...
-
嵌入式系统C编程之堆栈回溯
前言 在嵌入式系统C语言开发调试过程中,常会遇到各类异常情况.一般可按需添加打印信息,以便观察程序执行流或变量值是否异常.然而,打印操作会占用CPU时间,而且代码中添加过多打印信息时会显得很凌乱.此外 ...
-
ACM-ICPC 2018 徐州赛区网络预赛 C Cacti Lottery(暴力+期望)
链接https://nanti.jisuanke.com/t/31455 思路 首先先枚举把剩下的数填入星号的情况(其实就是枚举星号的排列),这是对方所能知道的所有信息,然后对方将取八种决策中最优的情 ...
-
Ubuntu16.04编译安装Redis Desktop Manager
Redis Desktop Manager for OSX&Ubuntu 的安装版是收费的, 如果自己编译则是免费的. 安装过程参考官方提供的文档 http://docs.redisdesk ...
-
Eclipse打JAR包,插件FatJar安装与使用
下载fatJar插件,解压缩后是一个.../plugins/(net...)把plugins下面的(net..)文件夹拷贝到eclipse 的plugins下,重新启动Eclipse3.1,Windo ...