Springboot2模块系列:security&oauth2(Token安全认证)

1 security认证

  • pom.xml
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
  • 默认用户名
    user
  • 密码
    启动spring-boot服务时自动生成,如:
    d9280802-b5de-4cdc-a036-f74211cd063d
  • 登录
http://localhost:8090/login
  • Postman登录
    post请求
    请求体:
{
	"username":"user",
	"password":"d9280802-b5de-4cdc-a036-f74211cd063d"
}

2 token认证

2.1 pom.xml

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.security.oauth</groupId>
      <artifactId>spring-security-oauth2</artifactId>
      <version>2.3.3.RELEASE</version>
    </dependency>

2.2 配置文件

  • 启动配置application-dev.yml
    配置连接Redis,参数如下表。
序号参数描述
1databaseRedis数据库编号
2host主机IP
3portRedis连接端口
4passwordRedis登录密码
5max-active连接池数据库最大连接数,0表示无限制
6max-idle连接池中最大空闲数
7max-wait建立连接的超时时间
8min-idle连接池中最小的空闲连接
spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: china@asia 
    jedis: 
      pool: 
        max-active: 8 
        max-idle: 8
        max-wait: -1ms 
        min-idle: 0
  • 角色用户及接口配置
    按照角色设置端口访问权限,如admin角色访问admin/**的端口。
package com.sb.config;

import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

@Configuration 
@EnableResourceServer 
public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
    @Override 
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception{
        resources.resourceId("rid").stateless(true);
    }
    @Override 
    public void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("admin")
            .antMatchers("/user/**").hasRole("user")
            .anyRequest().authenticated();
    }
}
  • token认证配置AuthorizationServerConfig.java
    生成Token时使用withClient值生辰请求Token的Authorization字段值。
序号参数描述
1withClient(“client”)用户名,client,用于生成base64编码
2accessTokenValiditySeconds(1800)token有效时间,单位:秒
3secret(new BCryptPasswordEncoder().encode(“123456”)密码模式,密码为123456
package com.sb.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.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.token.store.redis.RedisTokenStore;

@Configuration 
@EnableAuthorizationServer 
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
    @Autowired 
    AuthenticationManager authenticationManager;
    @Autowired 
    RedisConnectionFactory redisConnectionFactory;
    @Autowired 
    UserDetailsService userDetailsService;

    @Bean 
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override 
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
        clients.inMemory()
        .withClient("client")
        .authorizedGrantTypes("password", "refresh_token")
        .accessTokenValiditySeconds(1800)
        .resourceIds("rid")
        .scopes("all")
        .secret(new BCryptPasswordEncoder().encode("123456"));
    }

    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception{
        endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService);
    }

    @Override 
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception{
        security.allowFormAuthenticationForClients();
    }
}
  • 用户认证配置WebSecurityConfig.java
    指定用户生成特定的Token,这个Token用于该用户角色访问特定资源。
序号参数描述
1withUser(“admin”)用户名,admin,用于请求token
2password(new BCryptPasswordEncoder().encode(“123456”))用户密码,用于请求token
3secret(new BCryptPasswordEncoder().encode(“123456”)密码模式,密码为123456
package com.sb.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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Bean 
    @Override 
    public AuthenticationManager authenticationManagerBean() throws Exception{
        return super.authenticationManagerBean();
    }

    @Bean 
    @Override
    protected UserDetailsService userDetailsService(){
        return super.userDetailsService();
    }

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password(new BCryptPasswordEncoder().encode("123456"))
            .roles("admin")
            .and()
            .withUser("xiao")
            .password(new BCryptPasswordEncoder().encode("123456"))
            .roles("user");
    }

    @Override 
    protected void configure(HttpSecurity http) throws Exception{
        http.antMatcher("/oauth/**")
            .authorizeRequests()
            .antMatchers("/oauth/**")
            .permitAll()
            .and()
            .csrf()
            .disable();
    }
}

2.3 获取Token

  • cURL版接口
curl -X POST \
  'http://localhost:8090/oauth/token?grant_type=password&username=xiao&password=123456' \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic Y2xpZW50OjEyMzQ1Ng==' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Postman-Token: 9d89cd2b-5bb1-41ad-838e-91f8aef1266e'
  • java版接口
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("http://localhost:8090/oauth/token?grant_type=password&username=xiao&password=123456")
  .post(null)
  .addHeader("Authorization", "Basic Y2xpZW50OjEyMzQ1Ng==")
  .addHeader("Accept", "application/json")
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .addHeader("Cache-Control", "no-cache")
  .addHeader("Postman-Token", "ea2669a8-b183-4aa4-91b9-ba2160a16dd1")
  .build();

Response response = client.newCall(request).execute();
  • 请求参数配置
序号参数描述
1Authorization认证字段,格式为Basic base64编码,其中Basic为一个空格,base64编码为token配置中的用户和密码的base64编码,格式为:username:password如client:123456
2Accept接受数据格式
3Content-Type数据内容类型

在这里插入图片描述

图2.1 请求样例
  • 返回
{
    "access_token": "d9c0dd23-76d9-4b04-a732-bf62556d3979",
    "token_type": "bearer",
    "refresh_token": "a3ccc65e-b117-4c96-8d7a-bce2cc180cee",
    "expires_in": 1799,
    "scope": "all"
}

2.4 刷新Token

  • cURL版接口
curl -X POST \
  'http://localhost:8090/oauth/token?grant_type=refresh_token&refresh_token=895f5c39-4922-44f9-ab58-8cb6ac5c68e5' \
  -H 'Authorization: Basic Y2xpZW50OjEyMzQ1Ng==' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: cf384165-cec7-4368-8980-1b3d6cc3bb8e'

在这里插入图片描述

图2.2 刷新Token
  • 返回结果
{
    "access_token": "50728d50-672b-49df-81d4-114e4789389f",
    "token_type": "bearer",
    "refresh_token": "895f5c39-4922-44f9-ab58-8cb6ac5c68e5",
    "expires_in": 1799,
    "scope": "all"
}

2.5 添加Token请求接口

接口URL中添加access_token=获取token时生成的access_token

  • cURL版接口
curl -X GET \
  'http://localhost:8090/api/get-infos/all?access_token=d9c0dd23-76d9-4b04-a732-bf62556d3979' \
  -H 'Cache-Control: no-cache' \
  -H 'Postman-Token: 03666668-55cc-4c32-9cd7-cca3d1672255'
  • 前端接口
http://localhost:8090/api/get-infos/all?access_token=d9c0dd23-76d9-4b04-a732-bf62556d3979

在这里插入图片描述

图2.3 添加Token请求接口

3 小结

Token生成流程如图3.1。
在这里插入图片描述

图3.1 OAuth2 Token生成流程

【参考文献】
[1]https://blog.csdn.net/qq_37139980/article/details/90605708
[2]https://blog.csdn.net/u012613251/article/details/81279060
[3]https://www.cnblogs.com/rwxwsblog/p/5846752.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值