Spring security + oauth2.0 + redis + mybatis plus 搭建微服务
上个星期一个朋友请求帮忙,让我搭建一个分布式授权中心的微服务,之前我也没搭建过,在网上撸了几天前辈们写的技术博客,搞出个模型,分享给大家:
前辈们博客地址:
OAuth2.0 原理:https://blog.csdn.net/tclzsn7456/article/details/79550249
JWT 原理:https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=pc
以下是代码,我这个是通过密码模式进行认证的:
0.目录结构:
1.引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.7.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
2.编写配置类 AuthorizationParam 并在application.yml 中填写具体参数:
@Data
@ConfigurationProperties(prefix = "authorizationparam")
public class AuthorizationParam {
private String clientId; //客户端id
private String secret; //(可信客户端需要)客户端密钥
private String[] scopes; //客户受限范围
private String authorizedGrantTypes; // 授权客户端使用的授权类型
// private String authorities;//授予客户端的权限
private int tokenExpire;//token过期时间
private int tokenRefresh;//token 刷新时间
}
在application.yml 中填写具体参数:
authorizationparam:
client-id: 123456 #客户端id
secret: 123456 #(可信客户端需要)客户端密钥
scopes: read,write #客户受限范围
authorized-grant-types: password #授权客户端使用的授权类型
token-expire: 10000 #token过期时间
token-refresh: 1500 #token刷新时间
debug: true
3.编写OAuth2.0配置类,注意,这里我使用redis来存储令牌(token)和具体的用户信息,这边便于后期水平扩张:
package com.lmolong.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
/***
* OAuth 相关配置
*/
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
private static final String SECRETPREFIX = "{noop}"; //spring security5 之后需要
@Autowired
private AuthenticationManager authenticationManager; //认证管理者
@Autowired
private UserDetailsService userDetailsService; // 用户信息服务
@Autowired
private TokenStore tokenStore; //保存令牌数据栈
@Autowired
private AuthorizationParam authorizationParam;
@Override
public void configure(ClientDetailsServiceConfigurer clents) throws Exception {
clents.inMemory()
.withClient(authorizationParam.getClientId()) //客户端ID
.authorizedGrantTypes(authorizationParam.getAuthorizedGrantTypes(),"refresh_token")//设置验证方式
.scopes(authorizationParam.getScopes())
// .secret("{noop}secret")
.secret(SECRETPREFIX+authorizationParam.getSecret())
.accessTokenValiditySeconds(authorizationParam.getTokenExpire()) //token过期时间
.refreshTokenValiditySeconds(authorizationParam.getTokenRefresh());//refresh过期时间
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints){
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Bean
public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory){
// return new InMemoryTokenStore(); //使用内存存储令牌 tokeStore
return new RedisTokenStore(redisConnectionFactory); //使用redis存储令牌
}
}
4.编写web拦截、资源拦截 配置:
package com.lmolong.config;
import cn.hutool.crypto.SecureUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence)
{
return charSequence.toString();
//return SecureUtil.md5(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
//return SecureUtil.md5(charSequence.toString()).equals(s);
return charSequence.toString().equals(s);
}
});
// auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user1").password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
}
}
package com.lmolong.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable();
}
}
5.这里配置密码的加密方式,这里我暂时未加密:
package com.lmolong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//对任何请求做拦截,如果是完整认证的话,就允许访问
http.authorizeRequests().anyRequest().fullyAuthenticated();
//配置登陆连接,允许访问 --认证接口直接调用/oauth/token
http.formLogin().loginPage("/login").failureUrl("/login?code=").permitAll();
//配置登出连接,允许访问
http.logout().logoutUrl("/logout").permitAll();
http.authorizeRequests().antMatchers("/oauth/authorize").permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
6.扩张UserDetailService
package com.lmolong.service;
import org.springframework.security.core.userdetails.UserDetailsService;
//后期在此新增UserService的业务接口
public interface UserService extends UserDetailsService {
}
7.实现 UserService,扩展用户认证功能:
package com.lmolong.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lmolong.authbean.AuthUserDetail;
import com.lmolong.mapper.TUserMapper;
import com.lmolong.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.lmolong.pojo.TUser;
@Primary
@Service
public class UserServiceImpl implements UserService {
@Autowired
private TUserMapper tUserMapper;
@Override
public AuthUserDetail loadUserByUsername(String username) throws UsernameNotFoundException {
TUser param =new TUser();
param.setUsername(username);
TUser tUser = tUserMapper.selectOne(new QueryWrapper<>(param));
if(tUser==null){
throw new UsernameNotFoundException("用户不存在");
}else{
return UserDetailConverter.convert(tUser);
}
}
private static class UserDetailConverter {
static AuthUserDetail convert(TUser user) {
return new AuthUserDetail(user);
}
}
}
8.编写认证数据库实体类,注意,这里我用了lombok:
package com.lmolong.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TUser implements Serializable {
private Long id;
private String username;
private String password;
}
9.对应的Auth2.0权限封装类:
package com.lmolong.authbean;
import lombok.Data;
import org.springframework.security.core.userdetails.User;
import com.lmolong.pojo.TUser;
import java.util.Collections;
@Data
public class AuthUserDetail extends User {
private TUser tUser;
public AuthUserDetail(TUser user) {
super(user.getUsername(), user.getPassword(), true, true, true, true, Collections.EMPTY_SET);
this.tUser= user;
}
}
10.编写对应mapper接口:
package com.lmolong.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lmolong.pojo.TUser;
public interface TUserMapper extends BaseMapper<TUser> {
}
11.注意,在启动类中,我们要加上MapperScan注解:
package com.lmolong;
import com.lmolong.config.AuthorizationParam;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
@EnableConfigurationProperties({AuthorizationParam.class})
@MapperScan("com.lmolong.mapper")
public class SpringcloudOauth2Application {
public static void main(String[] args) {
SpringApplication.run(SpringcloudOauth2Application.class, args);
}
}
12.编写获取用户信息接口:
package com.lmolong.controller;
import com.lmolong.authbean.AuthUserDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import com.lmolong.pojo.TUser;
@RestController
public class UserController {
@Autowired
private TokenStore tokenStore;
@PostMapping("/auth")
public String auth(@RequestHeader("Authorization") String auth){
AuthUserDetail authUserDetail = (AuthUserDetail) tokenStore.readAuthentication(auth.split(" ")[1]).getPrincipal();
TUser tUser = authUserDetail.getTUser();
return tUser.getUsername()+":"+tUser.getPassword();
}
}
13.测试:
通过postman调用:http://localhost:8080/oauth/token 获取令牌
获取token成功:
使用 Redis Desktop manager 查看数据,发现数据已经存到redis中了:
访问接口,根据token获取用户信息:
获取成功。
至此,这个授权微服务整合完毕,当然,可能还有很多不完善的地方,期待大神指导,让我能更加完善它,在此感谢。
源码地址:https://gitee.com/lmolong/springcloud-oauth2
作者:L墨龙
原文:https://my.oschina.net/linwl/blog/2998036
Spring security + oauth2.0 + redis + mybatis plus 搭建微服务的更多相关文章
- springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)
项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖 ...
- Spring Security OAuth2.0认证授权二:搭建资源服务
在上一篇文章[Spring Security OAuth2.0认证授权一:框架搭建和认证测试](https://www.cnblogs.com/kuangdaoyizhimei/p/14250374. ...
- Spring Security OAuth2.0 - AuthorizationServer和ResourceServer分离
<Spring Security实现OAuth2.0授权服务 - 基础版>和<Spring Security实现OAuth2.0授权服务 - 进阶版>两篇文章中介绍如何搭建OA ...
- Spring Security OAuth2.0认证授权三:使用JWT令牌
Spring Security OAuth2.0系列文章: Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二: ...
- Spring Security OAuth2.0认证授权四:分布式系统认证授权
Spring Security OAuth2.0认证授权系列文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授 ...
- Spring Security OAuth2.0认证授权五:用户信息扩展到jwt
历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...
- Spring Security OAuth2.0认证授权六:前后端分离下的登录授权
历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...
- 【OAuth2.0】Spring Security OAuth2.0篇之初识
不吐不快 因为项目需求开始接触OAuth2.0授权协议.断断续续接触了有两周左右的时间.不得不吐槽的,依然是自己的学习习惯问题,总是着急想了解一切,习惯性地钻牛角尖去理解小的细节,而不是从宏观上去掌握 ...
- 基于spring boot2.0+spring security +oauth2.0+ jwt微服务架构
github地址:https://github.com/hankuikuide/microservice-spring-security-oauth2 项目介绍 该项目是一个演示项目,主要演示了,基于 ...
随机推荐
- FireMonkey下的WndProc实现
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Types, System.UI ...
- 编写按键驱动以及在framework层上报按键事件
平台信息:内核:linux3.10 系统:android6.0平台:RK3288 前言:本文主要实现的功能是在android系统中添加一个按键,在驱动层使用定时器,每隔1秒钟向上层发送按键实现,fra ...
- lvs+keepalived+nginx高性能负载均衡集群
项目发布时候,别人还能访问呢? 双机主从热备 LVS作用 LVS是一个开源的软件,可以实现传输层四层负载均衡.LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器.目前有 ...
- linux应用之gcc编译器的安装及使用
gcc是linux系统下功能十分强大的编译器. 本人使用的是CentOS 6.6 64位系统,由于在安装系统的时候并没有勾选安装gcc编译器,因此需要自行安装gcc编译器. 使用yum安装gcc 对于 ...
- DDD领域驱动之干货(二)
基于仓储的实现 1.前言:本着第一节写的有些糊涂,主要是自己喜欢实干,不太喜欢用文字表述,就这样吧.下面切入正题. 博客园里面有很多的大佬,我这里就不一一解释概览,有兴趣的朋友可以去看大佬们写的 ...
- 浏览器端JS导出EXCEL
浏览器端JS导出EXCEL FileSaver.js 实现了在本身不支持 HTML5 W3C saveAs() FileSaver 接口的浏览器支持文件保存.FileSaver.js 在客户端保存文件 ...
- linux c++ 连接mysql 数据库
Mysql是数据库中的主流,因此我一直以为在Linux下配置会很很容易,结果Google了大半天,大部分网页只说了如何安装Mysql之类的废话,对如何使用C/C++连接Mysql却只字不提,或者提的方 ...
- Opencv— — water wave
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- 2018值得选用的五个Linux服务器发行版
[IT168 编译]据最新统计,目前Linux发行版约有300种,几乎都可以作为服务器系统运行.在Linux早期,几乎所有发行版都是“万能”发行版,专门的Linux服务器发行版并不火热,到21世纪初, ...
- FFmpeg常用命令 (三)流媒体
前言 如此强大的FFmpeg,能够实现视频采集.视频格式转化.视频截图.视频添加水印.视频切片.视频录制.视频推流.更改音视频参数功能等.通过终端命令如何实现这些功能,Richy在本文做一记录,以备之 ...