微服务之Springboot整合Oauth2.0 + JWT

简介: 微服务之Springboot整合Oauth2.0 + JWT

公司要从单一架构转为微服务架构,特此记录

前期准备

初始依赖

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/>
  </parent>

使用spring boot 2.3.5.RELEASE,这是公司统一的版本

数据库脚本

Oauth数据库表,直接用官方的SQL表结构: sql表结构

或者用下面的

CREATE SCHEMA IF NOT EXISTS `oauth2` DEFAULT CHARACTER SET utf8 ;
USE `oauth2` ;

-- -----------------------------------------------------
-- Table `oauth2`.`clientdetails`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`clientdetails` (
  `appId` VARCHAR(128) NOT NULL,
  `resourceIds` VARCHAR(256) NULL DEFAULT NULL,
  `appSecret` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `grantTypes` VARCHAR(256) NULL DEFAULT NULL,
  `redirectUrl` VARCHAR(256) NULL DEFAULT NULL,
  `authorities` VARCHAR(256) NULL DEFAULT NULL,
  `access_token_validity` INT(11) NULL DEFAULT NULL,
  `refresh_token_validity` INT(11) NULL DEFAULT NULL,
  `additionalInformation` VARCHAR(4096) NULL DEFAULT NULL,
  `autoApproveScopes` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`appId`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_access_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_access_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) NULL DEFAULT NULL,
  `client_id` VARCHAR(256) NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL,
  `refresh_token` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_approvals`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_approvals` (
  `userId` VARCHAR(256) NULL DEFAULT NULL,
  `clientId` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `status` VARCHAR(10) NULL DEFAULT NULL,
  `expiresAt` DATETIME NULL DEFAULT NULL,
  `lastModifiedAt` DATETIME NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_client_details`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_details` (
  `client_id` VARCHAR(128) NOT NULL,
  `resource_ids` VARCHAR(256) NULL DEFAULT NULL,
  `client_secret` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `authorized_grant_types` VARCHAR(256) NULL DEFAULT NULL,
  `web_server_redirect_uri` VARCHAR(256) NULL DEFAULT NULL,
  `authorities` VARCHAR(256) NULL DEFAULT NULL,
  `access_token_validity` INT(11) NULL DEFAULT NULL,
  `refresh_token_validity` INT(11) NULL DEFAULT NULL,
  `additional_information` VARCHAR(4096) NULL DEFAULT NULL,
  `autoapprove` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`client_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_client_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) NULL DEFAULT NULL,
  `client_id` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_code`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_code` (
  `code` VARCHAR(256) NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_refresh_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_refresh_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

整合spring security

引入security的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

配置拦截

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {


    /**
     * 密码编码器
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
    
    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
        .passwordEncoder(passwordEncoder());
    }
    
    /**
     * 安全拦截机制
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/**").authenticated()
                .and()
                .formLogin().permitAll()
                .and()
                .csrf().disable();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

实现UserDetailsService ,加载用户信息

public class UserDetailsServiceImpl implements UserDetailsService {
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
    @Resource
    private BugLoginuserMapper userMapper;


    @SneakyThrows
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        BugLoginuser userInfo = userMapper.selectByPrimaryKey(username);
        if (userInfo == null) {
            log.error("Not found user:{}", username);
            throw new AuthException("用户不存在或密码错误");
        }

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority("Role_"+userInfo.getAuthtype());
        grantedAuthorities.add(authority);
        return new User(userInfo.getUserMainId(), userInfo.getUserPassword(), grantedAuthorities);
    }
}

整合oauth2.0

引入依赖

        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

编写认证服务器的拦截器,直接使用数据库进行存储认证信息

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Resource
    private DataSource dataSource;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private JwtTokenStore jwtTokenStore;

    @Resource
    private JwtAccessTokenConverter jwtAccessTokenConverter;



    @Bean
    public TokenStore tokenStore() {
//        //基于内存存储令牌
//        return new InMemoryTokenStore();
        //基于jdbc存储token
        return new JdbcTokenStore(dataSource);
    }

    /**
     * 令牌端点,设置令牌
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .tokenStore(jwtTokenStore)
                .accessTokenConverter(jwtAccessTokenConverter);
    }

    /**
     * 基于jdbc存储客户端信息,需要先进行配置
     *
     * @return
     */
    public ClientDetailsService clientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }

    /**
     * 配置客户端信息
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService());
    }

    /**
     * 配置令牌端点的安全约束
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")//tokenKey这个endpoint完全公开
                .checkTokenAccess("permitAll()")//checkToken这个endpoint完全公开
                .allowFormAuthenticationForClients();//允许表单验证
    }
}

访问如下链接

http://localhost:8088/oauth/authorize?client_id=client&response_type=code

被拦截到security的登录页面

输入用户名密码,会跳转到授权页面,点击授权就会回调到客户端

跳转到百度,拿到code码

https://www.baidu.com/?code=t2ocYs

拿着授权码去请求token

相关路径

/oauth/authorize:授权端点

/oauth/token:令牌端点

/oauth/confirm_access:用户确认授权提交端点

/oauth/error:授权服务错误信息端点

/oauth/check_token:用于资源服务访问的令牌解析端点

获取token

访问资源服务器


目录
相关文章
|
3天前
|
JSON 安全 Java
Spring Boot中使用JWT进行安全认证
Spring Boot中使用JWT进行安全认证
|
3天前
|
监控 Java 微服务
使用Spring Boot构建微服务架构
使用Spring Boot构建微服务架构
|
4天前
|
消息中间件 负载均衡 Java
最容易学会的springboot gralde spring cloud 多模块微服务项目
最容易学会的springboot gralde spring cloud 多模块微服务项目
|
29天前
|
监控 数据管理 Java
智慧城管源码,基于微服务+java+springboot+vue+uniapp开发的城管综合执法系统源码
智慧城管执法系统利用微服务和Java技术提升城市管理水平,涵盖事件处理、投诉、处罚等功能,包含PC和APP源码。系统支持执法APP,便于领导随时随地审批,具备文书模板、地图定位、法规查询等功能。此外,执法办案系统通过监控视频分析事件,实现案件全程闭环管理,包括组织、案件、信用和执法队伍管理,以及法规库等基础支撑。系统旨在优化流程,提高数据管理和效率。
智慧城管源码,基于微服务+java+springboot+vue+uniapp开发的城管综合执法系统源码
|
13天前
|
缓存 Java 微服务
Springboot微服务整合缓存的时候报循环依赖的错误 两种解决方案
Springboot微服务整合缓存的时候报循环依赖的错误 两种解决方案
13 1
|
3天前
|
SpringCloudAlibaba Java 微服务
微服务02,微服务技术对比,SpringBoot和SpringClound版本兼容
微服务02,微服务技术对比,SpringBoot和SpringClound版本兼容
|
25天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的微服务的车联网位置信息管理附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的微服务的车联网位置信息管理附带文章源码部署视频讲解等
20 1
|
5天前
|
存储 算法 安全
|
9天前
|
Kubernetes Java 微服务
使用Spring Boot构建微服务架构
使用Spring Boot构建微服务架构
|
9天前
|
JSON 安全 Java
Spring Boot中使用JWT进行安全认证
Spring Boot中使用JWT进行安全认证