我们知道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. 「雕爷学编程」Arduino动手做(33)——ESP-01S无线WIFI模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  2. Codeforces1157A(A题)Reachable Numbers

    A. Reachable Numbers Let's denote a function f(x)f(x) in such a way: we add 11 to xx, then, while th ...

  3. HTML5新特性--svg-echarts(重点)-拖动API-WebWorker

    一.html5新特性--svg--(折线/渐变特效对象/滤镜) #折线:多个坐标点组件一条折线 <polyline points="50,50 70,55 60,66 " s ...

  4. Angular核心概念之五---过滤器

    Filter:过滤器,用于在view中呈现数据时显示为另一种格式:过滤器的本质是一个函数,接收原始数据转换为新的格式进行输出: function(oldVal){ ... return newVal ...

  5. jquery live 区别

    http://www.360doc.com/content/13/1222/22/14022539_339358149.shtml 开始的时候在jQuery.1.7.1中使用了.live()觉得很好用 ...

  6. 用STM32的UART实现DMX512

    写在最前面: DMX512(digital multiplex) 其实就是主机向从机整包单向广播发送的协议(protocol),从机自取所需. 一.链接拓扑(network topology) 根据后 ...

  7. 新概念英语三 新东方主讲Lesson1

    新概念二 Lesson95 词汇 ①get a shock 吓了一跳,得到一个惊喜 例:his wife got a shock get into a such mess 这么不幸搞得一片狼籍弄得这样 ...

  8. c# 优化代码的一些规则——优先隐式类型[一]

    前言 说到底就是优先使用var,这个关键字,在c# 3.0中出现了. 首先要确认几点,一个就是var 是静态变量,而不是动态变量,也就是说使用var 你是不必去担心性能问题得, 百度百科: 1)静态存 ...

  9. redis的安装和简单操作

    安装gcc  目地是编译软件 yum install gcc-c++ 1.拷贝并解压 2.编译文件 到解压目录下 执行 make 进行编译依赖项 cd /deps make hiredis lua j ...

  10. Flexible 应用

    Flexibl.js 为我们做了一项工作,媒体查询工作,节约了许多操作 举个例子,移动端的页面设计稿是750px,我们自己换算rem单位,比如我想把屏幕划分为15等份,我就750/15=50,然后用所 ...