OAuth2

一、介绍

OAuth2是目前最流行的授权机制,用来授权第三方应用,获取用户数据。允许用户授权B应用不提供帐号密码的方式去访问该用户在A应用服务器上的某些特定资源。

资源所有者(Resource Owner):拥有受保护资源(如用户资料、照片、视频等)的用户。

客户端(Client):想要访问资源所有者资源的第三方应用程序。

授权服务器(Authorization Server):处理客户端的授权请求并发放访问令牌。

资源服务器(Resource Server):存储受保护的资源,并在访问令牌的授权下提供资源。

访问令牌(Access Token):授权服务器发放的用于访问资源的令牌。

回调URL(Callback URL):客户端在申请授权时提供的 URL,用于在授权成功后将访问令牌发送给客户端。

二、oauth2.0四个角色

资源所有者(Resource Owner):这是拥有受保护资源的用户。例如,一个用户可能有存储在云服务提供商的文件。

授权服务器(Authorization Server):这是处理请求和响应的中央服务器。它授权客户端访问资源所有者的资源。

资源服务器(Resource Server):这是存储和提供受保护资源的服务器。例如,云服务提供商可能会有一个资源服务器,它存储用户的文件。

客户端(Client):这是想要访问资源所有者的资源的客户端应用程序。例如,一个云存储同步工具的移动应用程序可能会扮演客户端的角色。

三、 四种授权模式

授权码(Authorization Code):

客户端向资源所有者请求授权。

资源所有者同意授权,并返回一个授权码。

客户端使用授权码向授权服务器请求访问令牌。

授权服务器验证授权码,并发放访问令牌。

隐藏式(Implicit):

客户端直接向资源服务器请求受保护的资源,并在 URL 中携带访问令牌。

资源服务器验证访问令牌,并响应请求。

密码式(Password):

客户端使用资源所有者的用户名和密码向授权服务器请求访问令牌。

授权服务器验证用户名和密码,并发放访问令牌。

客户端凭证(Client Credentials):

客户端使用其客户端凭证(如客户端ID和客户端密钥)向授权服务器请求访问令牌。

授权服务器验证客户端凭证,并发放访问令牌。

在实际应用中,根据应用程序的需求和安全性要求,开发人员可以选择适当的授权模式。对于Web应用程序,通常使用授权码或隐藏式;对于移动应用程序,通常使用隐藏式或客户端凭证。密码式通常不推荐使用,因为它可能会导致密码泄露。

四、OAUTH2的spring cloud 微服务单点登录

用户:就是注册的用户

客户端:就是我们的前端项目

授权服务器:我们可以专门在后台创建一个专门管授权的微服务

资源微服务:像其他的订单微服务,什么搜索微服务拉都可以看做用户能够访问的资源

五、 spring cloud alibaba 使用oauth2

  1. 创建父项目
  1. 启动nacos

3. 导入依赖

XML 复制代码
        <!-- 添加 OAuth2 依赖 -->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

        <!-- 添加 JWT 依赖 -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>1.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

**六、**授权码模式测试

1. 启动类中加入BCryptPasswordEncoder

java 复制代码
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

2. 写一个OauthConfig配置类

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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 javax.annotation.Resource;

@Configuration
@EnableAuthorizationServer
public class MyOauthConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    /*
     *  authorization_code 授权码模式
     *  password 密码模式
     *  client_credentials 客户端模式
     *  implicit 简单模式
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 将客户端的信息配置在内存中
                clients.inMemory()
                .withClient("admin")// 客户端id
                .secret(bCryptPasswordEncoder.encode("123456"))// 客户端密码
                .redirectUris("https://www.baidu.com")// 客户端重定向地址
                .scopes("all")// 客户端授权范围
                .authorities("all")// 客户端权限
                .authorizedGrantTypes("authorization_code")// 客户端授权类型
                .autoApprove(true);// 是否自动授权
    }
}

3.写一个security配置类

java 复制代码
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.annotation.Resource;


@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 允许访问"/oauth/**"路径的所有请求
        http.authorizeRequests()
            .antMatchers("/oauth/**").permitAll()
            // 其他所有请求需要进行身份验证
            .anyRequest().authenticated()
            // 允许表单登录
            .and()
            .formLogin().permitAll();

        // 禁用CSRF保护
        http.csrf().disable();
    }

    // 自定义用户的信息
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            // 设置用户名为"root"
            .withUser("root")
            // 设置密码为"123456",并使用BCryptPasswordEncoder进行加密
            .password(bCryptPasswordEncoder.encode("123456"))
            // 设置角色为"admin"
            .roles("admin");
    }
}

4. 配置端口号

5. 申请授权码

http://localhost:8086/oauth/authorize?response_type=code&client_id=admin&scop=all

输入之后回车会跳转到登录页面

输入账号密码

账号密码就是这个

输入账号密码后跳转

6. 根据授权码生成token

七、简单模式测试

1. 修改OauthConfig的配置类

2. 访问地址

http://localhost:8086/oauth/authorize?response_type=token&client_id=admin&scope=all

八、客户端模式测试

1. 修改OauthConfig的配置类

2. 访问

九、密码模式测试

1. 修改SecurityConfig的配置类

java 复制代码
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.annotation.Resource;


@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 允许访问"/oauth/**"路径的所有请求
        http.authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                // 其他所有请求需要进行身份验证
                .anyRequest().authenticated()
                // 允许表单登录
                .and()
                .formLogin().permitAll();
        // 禁用CSRF保护
        http.csrf().disable();

    }

    // 自定义用户的信息
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                // 设置用户名为"root"
                .withUser("root")
                // 设置密码为"123456",并使用BCryptPasswordEncoder进行加密
                .password(bCryptPasswordEncoder.encode("123456"))
                // 设置角色为"admin"
                .roles("admin");
    }

    // 获取认证管理器
    @Bean
    public AuthenticationManager geAuthManager() throws Exception {
        return super.authenticationManagerBean();
    }
}

2. 修改OauthConfig配置类

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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 javax.annotation.Resource;

@Configuration
@EnableAuthorizationServer
public class MyOauthConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private AuthenticationManager authenticationManager;

    /*
     *  authorization_code 授权码模式
     *  password 密码模式
     *  client_credentials 客户端模式
     *  implicit 简单模式
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 将客户端的信息配置在内存中
        clients.inMemory()
                .withClient("admin")// 客户端id
                .secret(bCryptPasswordEncoder.encode("123456"))// 客户端密码
                .redirectUris("https://www.baidu.com")// 客户端重定向地址
                .scopes("all")// 客户端授权范围
                .authorities("all")// 客户端权限
                .authorizedGrantTypes("password")// 客户端授权类型
                .autoApprove(true);// 是否自动授权
    }

    // 配置授权服务器的端点
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

3.访问

4. 不用输入第三方的用户名和密码

修改OauthConfig配置类

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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 javax.annotation.Resource;

@Configuration
@EnableAuthorizationServer
public class MyOauthConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private AuthenticationManager authenticationManager;

    /*
     *  authorization_code 授权码模式
     *  password 密码模式
     *  client_credentials 客户端模式
     *  implicit 简单模式
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 将客户端的信息配置在内存中
        clients.inMemory()
                .withClient("admin")// 客户端id
                .secret(bCryptPasswordEncoder.encode("123456"))// 客户端密码
                .redirectUris("https://www.baidu.com")// 客户端重定向地址
                .scopes("all")// 客户端授权范围
                .authorities("all")// 客户端权限
                .authorizedGrantTypes("password")// 客户端授权类型
                .autoApprove(true);// 是否自动授权
    }

    /*
     * 配置授权服务器的端点
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
    /*
     * 配置授权服务器的安全性
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients() // 允许客户端使用表单进行身份验证
                .checkTokenAccess("permitAll()") // 检查访问令牌的访问权限,允许所有
                .tokenKeyAccess("permitAll()"); // 检查访问令牌密钥的访问权限,允许所有
    }
}

5. 校验token

路径

localhost:8086/oauth/check_token?

6. 手动生成Token,解析Token

java 复制代码
package org.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;


import javax.annotation.Resource;

@Configuration
@EnableAuthorizationServer
public class MyOauthConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private AuthenticationManager authenticationManager;

    /*
     *  authorization_code 授权码模式
     *  password 密码模式
     *  client_credentials 客户端模式
     *  implicit 简单模式
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 将客户端的信息配置在内存中
        clients.inMemory()
                .withClient("admin")// 客户端id
                .secret(bCryptPasswordEncoder.encode("123456"))// 客户端密码
                .redirectUris("https://www.baidu.com")// 客户端重定向地址
                .scopes("all")// 客户端授权范围
                .authorities("all")// 客户端权限
                .authorizedGrantTypes("password")// 客户端授权类型
                .autoApprove(true);// 是否自动授权
    }


   //  * 配置授权服务器的端点

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .tokenStore(getTokenStore()) // token存储的地方
                .accessTokenConverter(jwtAccessTokenConverter());// 生成token的bean   解析token的bean
    }

   //  * 配置授权服务器的安全性

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients() // 允许客户端使用表单进行身份验证
                .checkTokenAccess("permitAll()") // 检查访问令牌的访问权限,允许所有
                .tokenKeyAccess("permitAll()"); // 检查访问令牌密钥的访问权限,允许所有
    }


    @Bean
    public TokenStore getTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
   /* *
     *  生成token的bean
     *  解析token的bean*/

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("asd");
        return jwtAccessTokenConverter;
    }

}

7.自定义登陆

修改Securityconfig类

java 复制代码
package org.example.config;


import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.entity.ResponseMsg;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;


@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin().loginProcessingUrl("/userlogin")
                .successHandler((httpServletRequest, httpServletResponse, authentication) -> {
                    String username = httpServletRequest.getParameter("username");
                    String password = httpServletRequest.getParameter("password");
                    HttpRequest post = HttpUtil.createPost("http://localhost:8086/oauth/token");
                    post.form("grant_type","password");
                    post.form("client_id","admin");
                    post.form("client_secret","123456");
                    post.form("username",username);
                    post.form("password",password);
                    HttpResponse execute = post.execute();// 发送请求
                    String body = execute.body();
                    JSONObject entries = JSONUtil.parseObj(body);
                    Object accessToken = entries.get("access_token");
                    printJsonData(httpServletResponse,new ResponseMsg(200,"成功",accessToken));
                });

        // 允许访问"/oauth/**"路径的所有请求
        http.authorizeRequests()
                .antMatchers("/userlogin","/oauth/**").permitAll()
                // 其他所有请求需要进行身份验证
                .anyRequest().authenticated()
                // 允许表单登录
                .and()
                .formLogin().permitAll();
        // 禁用CSRF保护
        http.csrf().disable();

    }

    // 自定义用户的信息
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                // 设置用户名为"root"
                .withUser("root")
                // 设置密码为"123456",并使用BCryptPasswordEncoder进行加密
                .password(bCryptPasswordEncoder.encode("123456"))
                // 设置角色为"admin"
                .roles("admin");
    }

    // 获取认证管理器
    @Bean
    public AuthenticationManager geAuthManager() throws Exception {
        return super.authenticationManagerBean();
    }

    public void printJsonData(HttpServletResponse response, ResponseMsg responseMsg) {
        try {
            response.setContentType("application/json;charset=utf8");
            ObjectMapper objectMapper = new ObjectMapper();
            String s = objectMapper.writeValueAsString(responseMsg);
            PrintWriter writer = response.getWriter();
            writer.print(s);
            writer.flush();
            writer.close();
        }catch (Exception e){
            e.printStackTrace();

        }
    }

}

访问

8.order

写一个order

写一个配置类

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
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
@EnableResourceServer
@EnableGlobalMethodSecurity(jsr250Enabled = true,prePostEnabled = true,securedEnabled=true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 其他所有请求需要进行身份验证
                .anyRequest().authenticated()
                // 允许表单登录
                .and()
                .formLogin().permitAll();
        // 禁用CSRF保护
        http.csrf().disable();

    }
    @Bean
    public TokenStore getTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("root");
        return jwtAccessTokenConverter;
    }

}

controller

java 复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping
    public String test(){
        return "成功";
    }
}

resouce配置文件

测试

相关推荐
Narutolxy2 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
Hello.Reader10 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默20 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood27 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑30 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb421528733 分钟前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶33 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_4336184435 分钟前
shell 编程(二)
开发语言·bash·shell
zfoo-framework41 分钟前
【jenkins插件】
java