OAuth + Security - 6 - 自定义授权模式
我们知道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 ...
随机推荐
- 不会看 Explain执行计划,劝你简历别写熟悉 SQL优化
昨天中午在食堂,和部门的技术大牛们坐在一桌吃饭,作为一个卑微技术渣仔默默的吃着饭,听大佬们高谈阔论,研究各种高端技术,我TM也想说话可实在插不上嘴. 聊着聊着突然说到他上午面试了一个工作6年的程序员, ...
- Java——Json字符串与Object互转
public static void JacksonTest() {//推荐 //{"MNG001":[{"ID":"1","PW ...
- VMware虚拟机,vps忘记密码修改密码
因为业务经常会用到虚拟机,然后过不了多久,登录密码就用不了. 解决问题有两种办法,其中一种是通过Dos命令窗:还有一个就是通过制作pe启动盘来操作,进行密码重置,删除等等. 制作pe启动盘的方式有 ...
- layui加tp5图片上传实例
<div class="layui-fluid"> <div class="layui-row"> <form class=&qu ...
- pycharm安装Numba失败问题
相关环境变量: pycharm Python 3.8 pip 19.3.1 Numba各个版本都不行 报错内容: Looking in indexes: https://pypi.tuna.tsing ...
- Docker安装常见的应用与将本地镜像推送到阿里云
一.Docker安装常用的应用 1,docker安装mysql #拉取镜像mysql5.7 docker pull mysql:5.7 #启动容器(绑定对应的配置文件和日志,默认密码为123456) ...
- jQuery-键值对理解
1.form表单 <form action='url' method='get/post'> <input type='text'/> <input type='pass ...
- PowerPC-MPC56xx Flash模式启动过程
https://mp.weixin.qq.com/s/SpBOfzJJ1OizYP-rsLJVqQ Flash启动模式为最常用模式. 一般情况下,芯片上电之后,从flash起始位置读取第一条指令的 ...
- jchdl - RTL Module
https://mp.weixin.qq.com/s/Sr4ffU4TPPoUJpdInwWd6w jchdl Module类在概念上对应Verilog的module,作为所有用户自定义模块的父 ...
- undefined和nul