SSO单点登录之用户认证实践

SSO单点登录之用户认证实践

背景

随着微服务的兴起,单点登录功能呢也随之而来,在登录每个服务的时候,我们应该遵循哪些规则,来认证访问的合法性呢?今天我们来聊聊基于Oauth2的认证规则.(这里就略过添加依赖,准备物料类等步骤我这里直接说明认证部分),

第一步:定义Security配置类

此类的作用是配置认证规则

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 初始化加密对象,此种加密方式是不可逆的,相比于MD5更加安全
     * 交给spring管理
     * */
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 提供一个负责认证的对象,此对象在基于Oauth2认证时使用
     * 交给spring管理
     * */
    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

重要类:BCryptPasswordEncoder
此类加密是Spring Security 官方推荐的密码解析器,实际应用中也是使用这个加密器居多。BCryptPasswordEncoder是对bcrypt强散列方法的具体实现,是基于Hash算法的单向加密,允许通过Strength参数控制加密强度,默认为10,基于此类进行测试密码加密

package com.qty;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@SpringBootTest
public class BCryptPasswordEncoderTest {

    @Test
    void BCPasswordTest(){
        // 定义密码
        String pwd = "qtycode";
        System.out.println("未加密密码:" + pwd);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        // 通过encode方法对密码进行加密
        String encode = passwordEncoder.encode(pwd);
        boolean result = passwordEncoder.matches("qtycode", encode);
        System.out.println("加密后密码:"+encode);
        System.out.println("对比结果:"+ result);

    }
}

打印结果
在这里插入图片描述

第二步:定义Oauth2认证授权配置

在这里我们首先根据生活中的实际情况考虑一个问题,在生活中什么时候需要认证呢?比如刷卡乘车,是否需要解析你这个卡的用户是谁,余额是否充足等,再比如公司中的CRM系统,是否需要认证你所访问的服务是否有权限等,所以基于实例,Oauth2也有自己的一套认证规则,这套规则规定了认证系统需要哪些对象

1)系统资源–>数据

2)资源拥有者–>用户

3)管理资源服务器

4)对用户进行认证和授权的服务器

5)客户端系统–>负责提交用户的信息

再来分析,对于认证授权系统来说需要构建哪些对象来完成认证
再拿生活中例子说明,比如说,想做一名老师,那么就需要考取教师资格证,那我们去哪考呢?教管局会提供一个报考的入口,我们通过这个入口,填写相应的个人信息,最终审核通过了,就会生成一个准考证,拿着准考证去参加考试,进考场时,还需要有一名监考老师检查你与准考证上的信息是否相符,如果相符就可以参考.
Oauth2认证授权的过程也是如此,

1)提供认证入口:这相当于教资报名的地方

​这里的入口指的是一个认证路径:
http://IP地址:端口号/oauth/token
http://IP地址:端口号/oauth/check_token等

2)认证信息:客户端发来请求时所携带什么信息,比如账号密码,相当于报名时填写个人信息

3)负责认证的对象:也就是谁来对客户端的请求进行认证,这相当于监考老师,检查信息是否相符合.

package com.qty.auth.service.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;

@Configuration
@EnableAuthorizationServer //在oauth2规范中启动认证和授权
@AllArgsConstructor
public class OauthConfig extends AuthorizationServerConfigurerAdapter {
    
    //@Autowired
    private BCryptPasswordEncoder passwordEncoder;
    //@Autowired
    private AuthenticationManager authenticationManager;
	//@Autowired
    private TokenStore tokenStore;
    //@Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    // 提供认证入口
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
       security.tokenKeyAccess("permitAll()") // 发布认证入口 /oauth/token
               .checkTokenAccess("permitAll()") // 发布检察令牌入口 /oauth/check_token
               .allowFormAuthenticationForClients(); // 允许用户以表单形式提交

        // super.configure(security);
    }

    // 客户端请求携带信息

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //super.configure(clients);
        clients.inMemory()
                .withClient("gateway-client") // 客户端标识
                // 秘钥,这里直接注入此对象即可
                .secret(passwordEncoder.encode("123456"))
                // 指定认证类型
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("all"); // 作用域,包含规定的客户端都可进行认证
    }

    // 负责认证的对象,认证成功颁发令牌,默认令牌是UUID


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //super.configure(endpoints);
        // 提供认证对象,此对象已写好,直接注入即可
        endpoints.authenticationManager(authenticationManager)
                //设置令牌服务,不设置默认是UUID,此次我们使用JWT
                .tokenServices(tokenServices())
                //设置允许请求方式,默认是post
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);

    }

    @Bean
   public AuthorizationServerTokenServices tokenServices(){
        // 生成token对象
        DefaultTokenServices ts = new DefaultTokenServices();
        // 设置令牌生成方式
        ts.setTokenStore(tokenStore);
        // 设置令牌增强,此对象还没写,报错没关系
        ts.setTokenEnhancer(jwtAccessTokenConverter);
        // 令牌有效时长
        ts.setAccessTokenValiditySeconds(3600);
        // 设置刷新令牌以及时长
        ts.setSupportRefreshToken(true);
        ts.setRefreshTokenValiditySeconds(3600*24);
        return ts;
    }
}

第三步:定义认证策略

我们使用JWT规则

package com.qty.auth.service.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.JwtTokenStore;



@Configuration
public class TokenConfig {

    /**
     * 配置令牌生成策略,oauth2提供了以下几种策略
     * 1.JdbcTokenStore:将token储存到关系型数据库,不建议,数据太大的情况效率很低
     * 2.RedisTokenStore:将token储存到缓存数据库redis
     * 3.JwtTokenStore:将token储存到储存到客户端,token中包含一些用户信息
     * 等等
     * */

    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * 设置令牌的创建以及验证方式
     * */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {

        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        // 设置令牌的加密密码
        jwtAccessTokenConverter.setSigningKey(SINGING_KEY);
        return jwtAccessTokenConverter;
    }

    private static final String SINGING_KEY = "auth";


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值