我们知道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);
}

参考资料:

https://github.com/spring-projects/spring-security-oauth/blob/master/tests/annotation/custom-grant/src/main/java/demo/Application.java

OAuth + Security - 6 - 自定义授权模式的更多相关文章

  1. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  2. IdentityServer4 自定义授权模式

    IdentityServer4除了提供常规的几种授权模式外(AuthorizationCode.ClientCredentials.Password.RefreshToken.DeviceCode), ...

  3. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

    一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...

  4. 转 - spring security oauth2 password授权模式

    原贴地址: https://segmentfault.com/a/1190000012260914#articleHeader6 序 前面的一篇文章讲了spring security oauth2的c ...

  5. IdentityServer4 实现自定义 GrantType 授权模式

    OAuth 2.0 默认四种授权模式(GrantType): 授权码模式(authorization_code) 简化模式(implicit) 密码模式(password) 客户端模式(client_ ...

  6. 【.NET Core项目实战-统一认证平台】第十四章 授权篇-自定义授权方式

    [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何强制令牌过期的实现,相信大家对IdentityServer4的验证流程有了更深的了解,本篇我将介绍如何使用自定义的授权方 ...

  7. Spring Security OAuth2 Demo —— 隐式授权模式(Implicit)

    本文可以转载,但请注明出处https://www.cnblogs.com/hellxz/p/oauth2_impilit_pattern.html 写在前面 在文章OAuth 2.0 概念及授权流程梳 ...

  8. Spring Security如何优雅的增加OAuth2协议授权模式

    一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...

  9. SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端

    目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...

随机推荐

  1. Kubernetes fabric8 JavaAPI

    Kubernetes fabric8 JavaAPI 一.依赖准备 <dependency> <groupId>io.fabric8</groupId> <a ...

  2. scroll 方法 获取滚轴距离顶部高度

    $(window).scroll(function(){ var supportPageOffset = window.pageXOffset !== undefined; // 判断是否支持page ...

  3. PAT-1078 Hashing (散列表 二次探测法)

    1078. Hashing The task of this problem is simple: insert a sequence of distinct positive integers in ...

  4. CF1013D Chemical table

    题目链接:http://codeforces.com/contest/1013/problem/D 题目大意: 给出一个 \(n \times m\) 的表格,表格上有一些初始点.若有这样的三个点:\ ...

  5. LeetCode上的SQL练习

    184. 部门工资最高的员工 SELECT D. NAME Department, E. NAME Employee, E.Salary FROM -- 内连接两张查询表 Employee E INN ...

  6. 纯python自研接口自动化脚本更新版本,让小白也能实现0到1万+的接口自动化用例

    查看完整文章点击原文链接:纯python自研接口自动化脚本更新版本,让小白也能实现0到1万+的接口自动化用例 你是否还在用postman\jmeter做接口自动化吗?用python的开源框架[unit ...

  7. ATX插件机制-学习学习

    添加插件:记录一下 https://testerhome.com/topics/16074 webview操作: https://testerhome.com/topics/12599

  8. NOI2006 最大获利 洛谷P4174

    洛谷题目传送门! 题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就 ...

  9. Docker 笔记一相关命令

    Centos 7 : Service network restart 重启网络 Ip addr 查看ip地址 Uname -r 查看内核版本 Yum install docker 安装docker 命 ...

  10. IDEA 插件推荐 —— 让你写出好代码的神器!

    概述 今天介绍的插件主要是围绕编码规范的.有追求的程序员,往往都有代码洁癖,要尽量减少代码的「坏味道」. 代码静态检查是有很多种类,例如圈复杂度.重复率等.业界提供了很多静态检查的插件来识别这些不合规 ...