这个例子是商城后台项目的一部分,主要使用了oAuth2的密码模式完成用户名密码认证功能。主要流程是:使用Nacos作为注册中心,操作用户的服务user-mgr-service作为服务提供者,注册到Nacos,通过Dubbo供oAuth2调用,同时oAuth2也作为Rest服务提供者,注册到Nacos,提供用户登录/user/login服务。网关Gateway也注册到Nacos,提供统一入口,路由到oAuth2服务,完成用户认证。

(文章主要写一下实现步骤,具体代码附上的话太多了,影响阅读。github.com/toyranger/c…)

1. Spring Security oAuth2 密码模式

1.1 密码模式和授权码模式

{placeholder}

2. oAuth2实现认证服务器

2.1 创建授权服务器

ClientDetailsServiceConfigurer:通过配置的数据源,配置ClientDetailsService

AuthorizationServerSecurityConfigurer:用来配置令牌端点(Token Endpoint)的安全约束.

AuthorizationServerEndpointsConfigurer:用来配置授权(authorization)以及令牌(token)

@Configuration

@EnableAuthorizationServer

public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

@Autowired

private BCryptPasswordEncoder passwordEncoder;

@Bean

@Primary

@ConfigurationProperties(prefix = "spring.datasource")

public DataSource dataSource() {

return DataSourceBuilder.create().build();

}

@Bean

public TokenStore tokenStore() {

return new JdbcTokenStore(dataSource());

}

@Bean

public ClientDetailsService jdbcClientDetailsService() {

return new JdbcClientDetailsService(dataSource());

}

/***

* 用于支持密码模式

*/

@Autowired

private AuthenticationManager authenticationManager;

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore());

}

@Override

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

// 允许客户端访问 /oauth/check_token检查token

security.checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();

}

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.withClientDetails(jdbcClientDetailsService());

}

/***

* 内存模式

*/

// @Override

// public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

//

// clients.inMemory()

// .withClient("client")

// .secret(passwordEncoder.encode("secret"))

// .authorizedGrantTypes("password", "refresh_token")

// .scopes("backend")

// .resourceIds("backend-resources")

// .accessTokenValiditySeconds(60 * 60 * 24)

// .refreshTokenValiditySeconds(60 * 60 * 24 * 30);

// }

}

复制代码

2.2 创建认证服务器和资源服务器

认证服务器的任务是根据用户名查询用户,以及用户所具有的权限,资源服务器的任务是配置访问资源(url)所需要的对应的权限。这里把他们写在一个Configuration中

@Configuration

@EnableWebSecurity

@EnableResourceServer

public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Bean

public BCryptPasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

}

@Bean

public UserDetailsService userDetailsService() {

return new UserDetailsServiceImpl();

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(userDetailsService());

}

/***

* 用于支持 password 模式

* @return

* @throws Exception

*/

@Bean

@Override

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

@Override

public void configure(WebSecurity web) throws Exception {

web.ignoring().antMatchers("/user/login");

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http.exceptionHandling().and()

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

.and()

.authorizeRequests()

.antMatchers("/user/info").hasAnyAuthority("UserInfo")

.antMatchers("/user/logout").hasAnyAuthority("UserLogout");

}

}

复制代码

2.3 在用户认证的userDetailsService中,需要通过Dubbo调用user-mgr-service提供的服务

public class UserDetailsServiceImpl implements UserDetailsService {

@Reference(version = "1.0.0")

private UserMgrApi userMgrApi;

@Reference(version = "1.0.0")

private PermissionMgrApi permissionMgrApi;

@Override

public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

User userByName = userMgrApi.selectOne(s);

if (null == userByName) {

return null;

}

List grantedAuthorities = Lists.newArrayList();

List permissions = permissionMgrApi.selectListByUserId(userByName.getId());

permissions.forEach(permission -> {

GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getEnname());

grantedAuthorities.add(grantedAuthority);

});

return new org.springframework.security.core.userdetails.User(userByName.getUsername(),

userByName.getPassword(), grantedAuthorities);

}

}

用户信息是基于RBAC授权模型,通过username查询用户,查到用户之后通过userId查询对应的权限,都是很简单的dao操作,使用mybatis(plus)就可以完成。

复制代码

3. oAuth2对外提供rest接口,/user/login

oAuth2密码需要传username、password、grant_type、client_id、client_secret五个参数,而用户只需要传username和password即可,所以其余的参数需要登录服务自己传过去。

这里使用RestTemplate,向oAuth2服务发起请求。

成功认证之后,会得到Token。

@PostMapping("/user/login")

public CommonsResponse login(@RequestBody LoginParam loginParam) {

String tokenUrl = "http://localhost:8091/oauth/token";

MultiValueMap multiValueMap = new LinkedMultiValueMap<>();

multiValueMap.add("username", loginParam.getUsername());

multiValueMap.add("password", loginParam.getPassword());

multiValueMap.add("grant_type", oauth2_grant_type);

multiValueMap.add("client_id", oauth2_client_id);

multiValueMap.add("client_secret", oauth2_client_secret);

HttpHeaders headers = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

HttpEntity> entity = new HttpEntity<>(multiValueMap, headers);

TokenEntity tokenEntity;

try {

tokenEntity = restTemplate.postForObject(tokenUrl, entity, TokenEntity.class);

} catch (Exception e) {

tokenEntity = null;

}

if (null == tokenEntity) {

return new CommonsResponse(BaseStatusEnum.UNAUTHORIZED.getIndex(),

BaseStatusEnum.UNAUTHORIZED.getMsg(), null);

}

return new CommonsResponse(BaseStatusEnum.SUCCESS.getIndex(), BaseStatusEnum.SUCCESS.getMsg(),

tokenEntity);

}

复制代码

4. 加入网关Gateway

网关可以限流和熔断,为应用提供统一的入口。这里只使用了基本的功能。

cloud:

nacos:

discovery:

server-addr: localhost:8848

gateway:

# 设置与服务注册发现组件结合,这样可以采用服务名的路由策略

discovery:

locator:

enable: true

routes:

- id: BUSINESS-OAUTH2

# 采用LoadBalanceClient方式请求,以lb://开头,后面跟注册在nacos上的服务名

uri: lb://business-security

# 断言,或者叫谓词

predicates:

- Path=/api/user/**

filters:

- StripPrefix=1

复制代码

5. 运行示例

5.1 注册到Nacos:

5.2 访问网关:

5.3 测试token权限

可以看到在资源服务中配置了

.antMatchers("/user/info").hasAnyAuthority("UserInfo"),即访问/user/info需要UserInfo权限,而此时RBAC表中,"user"用户具有这个权限

所以可以访问成功

此时如果我把"user"用户的/user/logout权限去掉(对应的表是tb_role_permission),那么他访问这个url的时候就会返回没有权限:

(好像是,修改了权限,之前获取的token就会失效,需要重新获取)

nacos oaut服务地址_用户认证的例子:Spring Security oAuth2 + Spring Cloud Gateway + Nacos + Dubbo...相关推荐

  1. nacos oaut服务地址_spring-boot+nacos+spring-oauth2整合方案

    spring-boot+nacos+spring-oauth2整合方案 介绍 微服务spring-boot和nacos的整合,结合开源项目若依前后端分离项目.以及自己研发的一些通用组件等等.项目包含z ...

  2. 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

  3. Spring Security OAuth2.0认证授权五:用户信息扩展到jwt

    历史文章 [Spring Security OAuth2.0认证授权一:框架搭建和认证测试] [Spring Security OAuth2.0认证授权二:搭建资源服务] [Spring Securi ...

  4. Spring Security Oauth2 JWT 实现用户认证授权功能

    Spring Security Oauth2 JWT 一 用户认证授权 1. 需求分析 1.1 用户认证与授权 什么是用户身份认证? 用户身份认证即用户去访问系统资源时系统要求验证用户的身份信息,身份 ...

  5. 从零开始超详细的Spring Security OAuth2.0实现分布式系统授权(注册中心+网关+认证授权服务(JWT令牌验证)+资源调用服务)

    文章目录 一.OAuth2.0 1.介绍 2.例子 3.执行流程 二.Spring Cloud Security OAuth2 1.环境介绍 2.认证流程 三.整合分布式项目 1.技术方案 2.项目结 ...

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

    本文源码地址 后端:https://gitee.com/youlaitech/youlai-mall/tree/v2.0.1 前端:https://gitee.com/youlaiorg/mall-a ...

  7. 基于 Spring Security OAuth2和 JWT 构建保护微服务系统

    我们希望自己的微服务能够在用户登录之后才可以访问,而单独给每个微服务单独做用户权限模块就显得很弱了,从复用角度来说是需要重构的,从功能角度来说,也是欠缺的.尤其是前后端完全分离之后,我们的用户信息不一 ...

  8. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  9. Spring Security OAuth2.0认证授权知识概括

    Spring Security OAuth2.0认证授权知识概括 安全框架基本概念 基于Session的认证方式 Spring Security简介 SpringSecurity详解 分布式系统认证方 ...

最新文章

  1. TS流解析之PAT表格解析
  2. get_attribute中的value是什么类型的?_建设工程项目中都有什么类型的监理?
  3. linux 中文意思,linux 中 ~/. 是什么意思
  4. unity 彩带粒子_Unity3d粒子特效:制作火焰效果
  5. Python基础 —— sys 模块
  6. 【万字详解】cJSON解析
  7. 学习笔记:EPS高级功能1-车道保持辅助LKA(Lane Keeping Assist)
  8. 【22年新版】软件工程专业的各阶段的学习方法
  9. python找最大值的函数_python求最大值
  10. 金武彩印机械设备有限公司仓储管理系统设计与实现
  11. 解决java下载文件中文文件名乱码问题(ie,谷歌,火狐)
  12. 程序员装B小技巧——管理你的桌面
  13. 音视频播放器开发——实现变速播放
  14. 微信企业支付RSA加密报错
  15. 亚马逊AWS·优维科技EASYOPS企业云计算研讨会 邀请函
  16. 小黄鸭调试法:拯救那些开发心里“无力回天”的bug
  17. 程序员一直在找的日程安排工具
  18. NOI模拟 五彩斑斓
  19. HDU-2121-Ice_cream’s world II
  20. scratch制作2022世界杯足球小游戏

热门文章

  1. c语言 位域 sizeof,含位域结构体的sizeof
  2. jfinal mysql增删改查_Jfinal简单实现增删改查
  3. cserialport 循环发送信号_10个动作三个循环,练完至少瘦一圈,吃多了也不用担心...
  4. php随机数字不重复使等式成立_当随机数遇上量子
  5. 2006---2009年杭电计算机历年研究生复试---笔试编程
  6. Linux C语言错误处理
  7. 关于服务器的入门知识整理
  8. 自己实现一个和PYTHON的库一模一样的sha_256算法
  9. Mysql Order By 注入总结
  10. 深入分析Flex [Bindable] 【转】