Spring Cloud OAuth2.0安全之路(一) 搭建OAuth2.0服务

Spring Cloud OAuth2.0安全之路(一) 搭建OAuth2.0服务

1.创建SpringBoot项目,导入相关的包,工程结构如下:

在这里插入图片描述

2.pom文件代码示例:

	<parent>
        <artifactId>cloud-root</artifactId>
        <groupId>com.cto.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-jdbc</artifactId>
        </dependency>
    </dependencies>

parent在父pom中有引入公共jar,核心内容如下:

	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
        <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3.配置AOuth2.0

先贴代码

@Configuration
@EnableJdbcHttpSession
@EnableAuthorizationServer
public class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public TokenStore tokenStore() {
//        return new JdbcTokenStore(dataSource);
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//        converter.setSigningKey("qRU5LLDPOJ0s7niuE!LyjETh*EPKdOE9TBURAhWS2n3fAXXy#!mqdPDljOHInWGf");  //签名的key
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("594cto.jks"), "123456".toCharArray());
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("594cto"));
        return converter;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.userDetailsService(userDetailsService)
                 .tokenStore(tokenStore())
                 .tokenEnhancer(jwtAccessTokenConverter())
                 .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       /* clients.inMemory()
                .withClient("order")       //应用ID
                .secret(passwordEncoder.encode("123456"))    //应用密码
                .scopes("read","write")      //应用权限
                .accessTokenValiditySeconds(1800)     //token的失效时间
                .resourceIds("order-server")       //允许访问的服务ID
                .authorizedGrantTypes("password");     //授权方式*/
       clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("isAuthenticated()") //暴露验证服务/oauth/token_key   permitAll()为关闭
                .checkTokenAccess("isAuthenticated()");//暴露验证服务/oauth/check_token
    }
}

TokenStore我采用了jwt的方式,也可以用jdbc或者redis
JwtAccessTokenConverter 配置JWT,其中.jks密钥文件可以通过keytool命令生成,具体可以自行查一下资料,一段命令即可。
ClientDetailsServiceConfigurer 该配置我采用了jdbc存库的方式,Spring已经写好了所有的方法,只需要自己新建数据表即可,如下:

CREATE TABLE `oauth_client_details` (
  `client_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '服务ID',
  `resource_ids` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '可访问哪些服务,为空则是全部',
  `client_secret` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '访问密码',
  `scope` varchar(256) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `authorized_grant_types` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '加密方式一共四种,目前使用了两种',
  `web_server_redirect_uri` varchar(256) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `authorities` varchar(256) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL COMMENT 'token有效期',
  `refresh_token_validity` int(11) DEFAULT NULL COMMENT 'refreshToken有效期',
  `additional_information` varchar(4096) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `autoapprove` varchar(256) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO `cloud-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('order', NULL, '$2a$10$I/Nei5gpxssWZchTx5Or6O4KQlcI5PW7FgbUM2.bRE7ZJHf65QAQW', 'read,write', 'password,refresh_token', NULL, NULL, 3600, 7200, NULL, NULL);
INSERT INTO `cloud-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('price', NULL, '$2a$10$I/Nei5gpxssWZchTx5Or6O4KQlcI5PW7FgbUM2.bRE7ZJHf65QAQW', 'read,write', 'password,refresh_token', NULL, NULL, 3600, 7200, NULL, NULL);
INSERT INTO `cloud-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('zuul', NULL, '$2a$10$I/Nei5gpxssWZchTx5Or6O4KQlcI5PW7FgbUM2.bRE7ZJHf65QAQW', 'read,write', 'password,refresh_token', NULL, NULL, 3600, 7200, NULL, NULL);

WebSecurityConfigurer配置如下:

@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private UserDetailsService userDetailsService;

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService)
			.passwordEncoder(passwordEncoder());
	}
	
	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

}

UserDetailsService需要手动去实现一下,验证用户信息在此处做

@Component
public class UserDetailsServiceImpl implements UserDetailsService {
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private FrontUserMapper frontUserMapper;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

		FrontUser frontUser = frontUserMapper.queryFrontUserByName(username);
		if(frontUser == null){
			throw new OAuth2Exception("用户名不存在");
		}
		return User.withUsername(username)
					.password(passwordEncoder.encode(frontUser.getPassword()))
					.authorities("ROLE_ADMIN")
					.build();
	}

}

FrontUserMapper

@Repository
public class FrontUserMapper {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public FrontUser queryFrontUserByName(String username){
        List<FrontUser> list = jdbcTemplate.query("select * from front_user where user_name = ?",new BeanPropertyRowMapper<>(FrontUser.class), username);
        if(list != null && list.size() > 0){
            return list.get(0);
        }
        return null;
    }
}

Application启动类没变化,默认的就可以

@SpringBootApplication
public class AuthApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuthApplication.class, args);
    }

}

yml配置文件

spring:
  application:
    name: auth
  datasource:
    url: jdbc:mysql://localhost:3306/cloud-security?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: root1234
    driver-class-name: com.mysql.cj.jdbc.Driver

server:
  port: 9090
  servlet:
    session:
      timeout: 3600

至此,验证服务搭建完毕。

第一次写博客,主要目的是强迫自己加深理解,如果文中有不对的地方,欢迎各大佬指教。
有兴趣一起学的小伙伴可以加好友一起学习。
下一章写一下网关的配置

源码地址:https://gitee.com/bigger-xu/oauthZuul
喜欢的小伙伴可以请关注我的站点:我的站点

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值