既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
* Oauth2 控制器
*/
@RestController
@RequestMapping(“oauth”)
public class OAuthController {
@Resource
private TokenEndpoint tokenEndpoint;
@Resource
private HttpServletRequest request;
@PostMapping("token")
public ResultInfo postAccessToken(Principal principal, @RequestParam Map<String, String> parameters)
throws HttpRequestMethodNotSupportedException {
return custom(tokenEndpoint.postAccessToken(principal, parameters).getBody());
}
/\*\*
* 自定义 Token 返回对象
*
* @param accessToken
* @return
*/
private ResultInfo custom(OAuth2AccessToken accessToken) {
DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
Map<String, Object> data = new LinkedHashMap(token.getAdditionalInformation());
data.put(“accessToken”, token.getValue());
data.put(“expireIn”, token.getExpiresIn());
data.put(“scopes”, token.getScope());
if (token.getRefreshToken() != null) {
data.put(“refreshToken”, token.getRefreshToken().getValue());
}
return ResultInfoUtil.buildSuccess(request.getServletPath(), data);
}
}
#### 登录逻辑调整,增强令牌返回参数
添加登录认证对象:
package com.zjq.commons.model.domain;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 登录认证对象
*
* @Author zjq
* @Date 2022/10/12
*/
@Getter
@Setter
public class SignInIdentity implements UserDetails {
// 主键
private Integer id;
// 用户名
private String username;
// 昵称
private String nickname;
// 密码
private String password;
// 手机号
private String phone;
// 邮箱
private String email;
// 头像
private String avatarUrl;
// 角色
private String roles;
// 是否有效 0=无效 1=有效
private int isValid;
// 角色集合, 不能为空
private List<GrantedAuthority> authorities;
// 获取角色信息
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if (StrUtil.isNotBlank(this.roles)) {
// 获取数据库中的角色信息
Lists.newArrayList();
this.authorities = Stream.of(this.roles.split(",")).map(role -> {
return new SimpleGrantedAuthority(role);
}).collect(Collectors.toList());
} else {
// 如果角色为空则设置为 ROLE\_USER
this.authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE\_USER");
}
return this.authorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return this.isValid == 0 ? false : true;
}
}
登录后返回登录认证对象:
@Resource
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AssertUtil.isNotEmpty(username, "请输入用户名");
Users users = usersMapper.selectByAccountInfo(username);
if (users == null) {
throw new UsernameNotFoundException("用户名或密码错误,请重新输入");
}
// 初始化登录认证对象
SignInIdentity signInIdentity = new SignInIdentity();
// 拷贝属性
BeanUtils.copyProperties(users, signInIdentity);
return signInIdentity;
}
在授权服务配置类AuthorizationServerConfiguration中增强令牌返回信息:
/\*\*
* 配置授权以及令牌的访问端点和令牌服务
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 认证器
endpoints.authenticationManager(authenticationManager)
// 具体登录的方法
.userDetailsService(userService)
// token 存储的方式:Redis
.tokenStore(redisTokenStore)
// 令牌增强对象,增强返回的结果
.tokenEnhancer((accessToken, authentication) -> {
// 获取登录用户的信息,然后设置
SignInIdentity signInIdentity = (SignInIdentity) authentication.getPrincipal();
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put(“nickname”, signInIdentity.getNickname());
map.put(“avatarUrl”, signInIdentity.getAvatarUrl());
DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
token.setAdditionalInformation(map);
return token;
});
}
#### 测试验证
访问请求/oauth/token,可以看到已经返回我们自己需要的认证授权返回结果。
![在这里插入图片描述](https://img-blog.csdnimg.cn/cc876bf64feb4de584b3b84e934c8bae.png)
至此,认证授权微服务已经构建完成。
上述已经完成了认证授权中心的搭建。下面继续通过用户微服务访问认证中心实现登录退出。
接下来我们构建一个用户微服务并通过调用授权认证服务实现登录和退出。
### 用户微服务构建
用户服务相关pom依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
oauth2-demo
com.zjq
1.0-SNAPSHOT
4.0.0
<artifactId>ms-users</artifactId>
<dependencies>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- spring web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring data redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- commons 公共项目 -->
<dependency>
<groupId>com.zjq</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 自定义的元数据依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
配置文件内容如下:
server:
端口
port: 8082
spring:
application:
# 应用名
name: ms-users
数据库
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/oauth2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false
Redis
redis:
port: 6379
host: localhost
timeout: 3000
database: 1
password: 123456
swagger
swagger:
base-package: com.zjq.oauth2
title: 用户服务API接口文档
Oauth2 客户端信息
oauth2:
client:
client-id: appId
secret: 123456
grant_type: password
scope: api
配置 Eureka Server 注册中心
eureka:
instance:
prefer-ip-address: true
instance-id:
s
p
r
i
n
g
.
c
l
o
u
d
.
c
l
i
e
n
t
.
i
p
−
a
d
d
r
e
s
s
:
{spring.cloud.client.ip-address}:
spring.cloud.client.ip−address:{server.port}
client:
service-url:
defaultZone: http://localhost:8080/eureka/
oauth2 服务地址
service:
name:
ms-oauth-server: http://ms-oauth2-server/
Mybatis
mybatis:
configuration:
map-underscore-to-camel-case: true # 开启驼峰映射
指标监控健康检查
management:
endpoints:
web:
exposure:
include: “*” # 暴露的端点
logging:
pattern:
console: ‘%d{HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n’
#### 配置类构建
oauth2客户端配置类构建:
/**
* oauth2 客户端配置类
* @author zjq
*/
@Component
@ConfigurationProperties(prefix = “oauth2.client”)
@Getter
@Setter
public class OAuth2ClientConfiguration {
private String clientId;
private String secret;
private String grant_type;
private String scope;
}
编写redisTemplate相关配置类,调整默认的序列化方式。
![在这里插入图片描述](https://img-blog.csdnimg.cn/987d14c1c4f742eebc76879f03dda5c1.png)
编写远程请求配置类:
/**
* Rest 配置类
*/
@Configuration
public class RestTemplateConfiguration {
// 负载均衡请求
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
uration
public class RestTemplateConfiguration {
// 负载均衡请求
[外链图片转存中…(img-SyXY1CPd-1715905606324)]
[外链图片转存中…(img-LnCv5Mpg-1715905606324)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)