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 项目介绍 该项目是一个演示项目,主要演示了,基于 ...
随机推荐
- 美化你的APP——从Toolbar開始
Toolbar是什么 Toolbar是Google在Android 5.0中推出的一款替代ActionBar的View.ActionBar必须得作为Activity内容的一部分,而Toolbar能够放 ...
- Django中如何实现数据库路由?
虽然我们提供了数据库的信息,它知道怎么连接数据库,但问题是我们保存里面有很多模型,它不知道哪个模型存到哪个数据库.这就要求我们自己来指定,也就是我们自己来实现一个数据库路由.一个数据库路由是一个拥有4 ...
- PAT 天梯赛 L1-054. 福到了 【字符串】
题目链接 https://www.patest.cn/contests/gplt/L1-054 思路 可以先将字符串用字符串数组 输入 然后用另一个字符串数组 从 n - 1 -> 0 保存 其 ...
- Hamming校验码
可参考:http://winda.blog.51cto.com/55153/1068000 Hamming校验码作用:用于校验通信数据,防止出现错误,并具有一定的纠错功能. 汉明码在传输的消息流中插入 ...
- Unable to create Debug Bridge:Unable to start adb server:error:cannot parse version
打开Android Studio时报如下错误提示: Unable to create Debug Bridge:Unable to start adb server:error:cannot pars ...
- ubuntu熟悉过程中遇到一些小问题记录一下
0. 使用su命令时提示: authentication failur 安装ubuntu系统默认是没有激活root用户的,需要我们手工进行操作,在命令行界面下,或者在终端中输入如下命令:sudo p ...
- [FJOI 2016] 神秘数
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4408 [算法] 首先考虑一组询问怎样做 : 将数组按升序排序 , 假设我们现在可以表 ...
- [国家集训队]Crash的数字表格 / JZPTAB
传送门 题目要求,求: \[\sum_{i=1}^n\sum_{j=1}^mlcm(i,j)\] 先转化为gcd的形式,然后枚举gcd. \[\sum_{i=1}^n\sum_{j=1}^m\sum_ ...
- mybatis编写流程(老版本的方式,新版本用接口式编程)
1.根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象 有数据源一些运行环境信息2.sql映射文件:配置了每一个sql,以及sql的封装规则等. 3.将sql映射文件注 ...
- 基于候选区域的R-CNN系列网络简介
使用候选区域方法(region proposal method)创建目标检测的感兴趣区域(ROI).在选择性搜索(selective search,SS)中,首先将每个像素作为一组.然后,计算每一组的 ...