开放平台之认证中心搭建(二)

认证中心单独作为一个微服务工程,对开放平台提供应用id及密钥生成,token生成,认证信息缓存,token验证等一系列功能。开放平台access_token生成业界一般采用Oauth2的客户端模式。将来此认证中心微服务可随时扩展,除Oauth2的剩余三种授权模式授权码模式(应用场景:如第三方授权登录等)、密码模式(应用场景:如企业诸多内部系统登录等)、简化模式(应用场景:如平台与三方服务整合等)之外还可以自定义授权模式来满足各种实际场景,后续如果小伙伴们需要,我会结合企业实际应用案例详细介绍。

1.数据库表创建

create table `oauth_client_details` (
	`client_id` varchar (192),
	`resource_ids` varchar (1024),
	`client_secret` varchar (1024),
	`scope` varchar (1024),
	`authorized_grant_types` varchar (1024),
	`web_server_redirect_uri` varchar (1024),
	`authorities` varchar (1024),
	`access_token_validity` int (11),
	`refresh_token_validity` int (11),
	`additional_information` longtext,
	`autoapprove` varchar (1024)
); 

重要参数说明:

1.client_id:应用id(唯一),将来需要提供给三方调用者获取token使用。

2.client_secret:应用密钥(可修改),作用同client_id。

3.authorized_grant_types:支持的授权模式,针对开放平台此值为client_credentials。

4.access_token_validity:token有效期,一般开放接口access_token有效期为7200S。

2.引入pom文件

   <dependencies>
        <!-- springboot支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- oauth2支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>${spring-cloud-starter-oauth2.version}</version>
        </dependency>
        <!-- redis支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>${common-pool.version}</version>
        </dependency>
        <!-- lombok支持 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- mp支持 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
    </dependencies>

3.创建安全认证器

package com.auth.admin.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @desc 安全认证器
 * @author mj
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //配置HTTP安全规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf防护,允许用户访问/oauth开头的请求。
        http.csrf().disable().requestMatchers().antMatchers("/**").and().authorizeRequests()
            .antMatchers("/oauth/**").permitAll().anyRequest().permitAll();
    }


    //配置认证管理器AuthenticationManager
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //管理认证实现例如userDetail实现以及密码加密等。(密码模式会用到 客户端模式暂不用关心)
    }
}

4.创建认证配置(令牌端点、oauth2客户端、token配置等)

package com.auth.admin.config;

import java.util.Arrays;
import javax.annotation.Resource;
import javax.sql.DataSource;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

/**
 * @desc 认证配置
 * @author mj
 */
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private ClientDetailsService clientDetailsService;

    @Resource
    private TokenEnhancer tokenEnhancer;

    @Resource
    private DataSource dataSource;

    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    // 对称秘钥,资源服务器使用该秘钥来验证
    private static final String SIGN_KEY = "ABCDEF";

    //redis中认证信息存储前缀
    private static final String OAUTH_PREFIX = "CREATE_TOKEN:";


    //1 配置令牌端点 其实就是令牌相关的服务
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //初始化配置
        //配置对token key端点的访问控制
        security.checkTokenAccess("permitAll()")
            //配置对/oauth/check_token端点的访问控制 此端点通常是用来验证令牌token有效性
            .tokenKeyAccess("permitAll()")
            // 允许以应用/密码的方式访问/oauth/token端点。
            .allowFormAuthenticationForClients();
    }

    //2 配置oauth2客户端
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 客户端存储到数据库中
        clients.withClientDetails(createJdbcDetailsService());
    }

    //数据库加载客户端
    @Bean
    public JdbcClientDetailsService createJdbcDetailsService() {
        JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
        return jdbcClientDetailsService;
    }


    //3 配置授权及令牌服务(例如认证管理器、token存储等)
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            //重要:自定义令牌实现。
            .tokenServices(tokenServiceImpl());
    }
    //自定义实现令牌生成 存储 刷新等操作
    @Bean
    public AuthorizationServerTokenServices tokenServiceImpl() {
        //AuthorizationServerTokenServices 默认实现 此处也可以自定义实现token的一系列管理
        //例如你想自定义token过期后的策略等等 都可以在这里实现。
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        //token配置客户端信息存储 例如token的有效期 授权模式等等 均在数据库中进行管理。
        defaultTokenServices.setClientDetailsService(clientDetailsService);
        //支持刷新token。
        defaultTokenServices.setSupportRefreshToken(true);
        // 配置token的存储方法(业界一般用redis存储)。
        defaultTokenServices.setTokenStore(tokenStore());
        //token增强器 例如你想在token信息里边加一些附加信息 就可以在这里添加TokenEnhancer的实现。
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer,jwtAccessTokenConverter()));
        defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);
        return defaultTokenServices;
    }
    //token存储配置
    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
        //token存储前缀
        tokenStore.setPrefix(OAUTH_PREFIX);
        return tokenStore;
    }
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(SIGN_KEY);
        return jwtAccessTokenConverter;
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

5.客户端操作controller

package com.auth.admin.controller;

import com.auth.admin.service.IOauthClientDetailService;
import com.auth.admin.vo.ClientDetailReqVo;
import com.auth.admin.vo.ClientDetailVo;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc 客户端配置(用户给三方申请应用client_id及client_secret密钥)
 * @author mj
 */
@RestController
public class ClientDetailController {

    private static final Logger log = LoggerFactory.getLogger(ClientDetailController.class);

    @Resource
    private IOauthClientDetailService oauthClientDetailService;

    // 添加客户端配置信息
    @PostMapping("/client/detail/post")
    public Boolean addClientDetails(@RequestBody ClientDetailVo clientDetailVo){
        return oauthClientDetailService.addClientDetail(clientDetailVo);
    }

    // 查询客户端配置
    @PostMapping("/client/detail/get")
    public ClientDetailVo findClientDetails(@RequestBody ClientDetailReqVo clientDetailReqVo){
        return oauthClientDetailService.findClientDetails(clientDetailReqVo);
    }

}

6.客户端操作实现

package com.auth.admin.service.impl;

import com.auth.admin.mapper.OauthClientDetailMapper;
import com.auth.admin.model.OauthClientDetail;
import com.auth.admin.service.IOauthClientDetailService;
import com.auth.admin.vo.ClientDetailReqVo;
import com.auth.admin.vo.ClientDetailVo;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * @desc 客户端接口实现
 * @author mj
 */
@Service
public class OauthClientDetailServiceImpl extends ServiceImpl<OauthClientDetailMapper, OauthClientDetail> implements
    IOauthClientDetailService {

    @Override
    @Transactional
    public Boolean addClientDetail(ClientDetailVo clientDetailVo) {
        if(ObjectUtils.isEmpty(clientDetailVo)){
            return Boolean.TRUE;
        }
        OauthClientDetail oauthClientDetail=new OauthClientDetail();
        BeanUtils.copyProperties(clientDetailVo,oauthClientDetail);
        this.baseMapper.insert(oauthClientDetail);
        return Boolean.TRUE;
    }

    @Override
    public ClientDetailVo findClientDetails(ClientDetailReqVo clientDetailReqVo) {
        ClientDetailVo clientDetailVo=new ClientDetailVo();
        if(StringUtils.isEmpty(clientDetailReqVo.getClientId())){
            throw new IllegalArgumentException("clientId is not null");
        }
        OauthClientDetail clientDetail = new LambdaQueryChainWrapper<>(baseMapper).eq(OauthClientDetail::getClientId,
            clientDetailReqVo.getClientId()).one();
        if(ObjectUtils.isEmpty(clientDetail)){
            return clientDetailVo;
        }
        BeanUtils.copyProperties(clientDetail,clientDetailVo);
        return clientDetailVo;
    }
}

7.测试-(为三方分配应用)

8.测试-(查询客户端配置)

9.测试-(为三方生成access_token)

如需完整代码,请小伙伴们点赞加关注,私信我领取。创作不易,您的支持是我今后更新的最大动力。感谢!

  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
搭建openapi开放平台是为了提供给开发者一种简单、高效的方式来获取和使用公司的数据和服务。对于企业来说,搭建openapi开放平台可以带来许多好处。 首先,搭建openapi开放平台可以吸引更多的开发者加入到生态系统中,从而扩大公司的用户群体。开放平台可以为开发者提供高质量的API文档和开发工具,使得他们能够更快速、更方便地接入和使用公司的数据和服务。这样一来,更多的开发者将对公司的产品产生兴趣,并将其整合到自己的应用中,提高了公司产品的曝光度和用户粘性。 其次,搭建openapi开放平台可以促进合作伙伴关系的建立。通过开放平台,公司可以与各种各样的开发者、第三方应用和服务进行对接,形成生态系统的互通互联。这将为公司提供更多的商业机会,同时也能够增加合作伙伴的收入来源。 再者,搭建openapi开放平台可以加速产品创新和迭代。开放平台可以成为一个创新的实验场,公司可以通过与开发者的合作,获取更多的创意和灵感。开发者可以基于公司的数据和服务,开发出更多有趣、实用的应用和功能,为公司的产品增加新的价值。 最后,搭建openapi开放平台可以提高公司的技术影响力和行业地位。在开放的环境下,公司的技术实力和创新能力将更加突显。通过授权和支持开发者使用公司的API,可以树立公司在技术领域的权威地位,并在行业内树立良好的口碑。 总的来说,搭建openapi开放平台是一项重要的战略举措,能够带来许多商业上的好处,为企业的发展注入新的活力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值