欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Oauth2入门

程序员文章站 2023-12-22 18:51:58
...

Oauth2有以下授权模式:

  1. 授权码模式(Authorization Code)
  2. 隐式授权模式(Implicit)
  3. 密码模式(Resource Owner Password Credentials)
  4. 客户端模式(Client Credentials)

其中授权码模式和密码模式应用较多

授权码模式

授权码授权流程:

  1. 客户端请求第三方授权
  2. 认证服务器生成用户授权协议,用户同意授权,认证服务器将协议唯一号(授权码)响应给客户端
  3. 客户端获得授权码, 然后请求认证服务器申请令牌
  4. 认证服务器生成令牌后向客户端响应令牌
  5. 客户端请求资源服务器的资源,资源服务器校验令牌合法性,完成授权
  6. 资源服务器返回受保护资源

Oauth2入门

请求认证服务获取授权码

固定表名:oauth_client_details(此表名不可修改)

Get请求:
http://localhost:9200/oauth/authorize?
client_id=changgou&response_type=code&scop=app&redirect_uri=http://localhost



client_id:客户端id,和授权配置类中设置的客户端id一致。
response_type:授权码模式固定为code
scop:客户端范围,和授权配置类中设置的scop一致。
redirect_uri:跳转uri,当授权码申请成功后会跳转到此地址,并在后边带上code参数(授权码)

Oauth2入门

获取令牌【授权码模式】

Post请求:
http://localhost:9200/oauth/token

【header】
clinet_id:客户端名
client_secret:客户端密码

【body】
grant_type:授权类型,填写authorization_code,表示授权码模式
code:授权码,就是刚刚获取的授权码,注意:授权码只使用一次就无效了,需要重新申请。
redirect_uri:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。

【Authorization】
TYPE:Basic Auth
username:账号
password:密码





{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYwMDYzMDU2MiwianRpIjoiMTBlNThkYWMtMzRmZC00OWQxLThlZjctZGUzYzZlZjU3Mzg5IiwiY2xpZW50X2lkIjoiY2hhbmdnb3UiLCJ1c2VybmFtZSI6ImNoYW5nZ291In0.JrDYPSqooM57epYYdiipMf6tC9i6MZolySHf4an4BbTcZIvqLy39UIsXPK27bL8LGtaaZYFKW0FKHuNlUrX5hg8qCZhOuzOJGAJfGAFf1DiVCOVph-pE4P0va3MXkUYmLSXxgcJBSTuG31L3nnatvPU0__WfbjnJjAD_DWb20wOtET4E8Iv2L1kcmtSSswYnlY6actlqfdns93JHmZewPh8i647H0rvBzIlO0N6ZMkmfWxRL9dMv80dwSMCmsvHD0W0I8w4c8Ns18iwzYFPjqtEajlcW6DmERI1sd94aUl96cBD0uijpgpec226KclZ8h-_oRzGb3pSAqiaJQX711w",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwiYXRpIjoiMTBlNThkYWMtMzRmZC00OWQxLThlZjctZGUzYzZlZjU3Mzg5IiwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYwMDYzMDU2MiwianRpIjoiMDAzN2Q4MzUtYzQ0OC00NjI5LWI2MTYtMmNmNDVkNDQxYzc3IiwiY2xpZW50X2lkIjoiY2hhbmdnb3UiLCJ1c2VybmFtZSI6ImNoYW5nZ291In0.hbksRM6PkOPEcBs7VS5W8-EUNSraKo5TWgjJk53tZC6rOxyTGd9HOf7dM6CDZ9GuEKoSWVSARMcyYU6RyGJrkURc4VBBXjGydrO3Zn7esoR291CVS8gLLjoMhYwq_rchgrsx9P6MOIT0PapsQr321I7d6EwYR7zKU8cuMA0L1HqewpZxjP1BtVtMln52CUADqzYa8uuPb4FkORbfzVR-mjBZrkM96lXxa5z2asMEBsve9CGxhXGvaWW5Iw_DNNpjbYvT5v2qJ5z7BzaUydmzhoX_GIcyo2UedycoevBgSItIEE-C7vSUvHswuL_aUsRBxCsdBe2AqJZE-r4mQ5EZoQ",
    "expires_in": 43199,
    "scope": "app",
    "jti": "10e58dac-34fd-49d1-8ef7-de3c6ef57389"

校验令牌

Get请求:
http://localhost:9200/oauth/check_token?token=[access_token]



结果:
{
    "scope": [
        "app"
    ],
    "name": null,
    "active": true,
    "id": null,
    "exp": 1600630562,
    "jti": "10e58dac-34fd-49d1-8ef7-de3c6ef57389",
    "client_id": "changgou",
    "username": "changgou"
}

刷新令牌(令牌和时间都会更新)

Post:http://localhost:9200/oauth/token
参数:
grant_type: 固定为 refresh_token
refresh_token:刷新令牌(注意不是access_token,而是refresh_token)



结果:
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwiZXhwIjoxNjAwNjMyMTkxLCJqdGkiOiJkMGMwMzRkZS00YjY5LTQ1YTYtODIyZi00NTkxMDg0OWVjMWUiLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSJ9.iLcwZUHjeFHKWwt_54CpxEEiPpzPqjHJSNeq5RYctGNygmFu-HxhOgRy83h2st-GucfIPGyEPiDt2JtndwhWVpdLY0JrrF2n2zeFLEtuc1Y7IzoJrsBKyHSN6sDErkdwnxuKAVGXIFp8miQy1qXsR7SN-LQ5i1j8S56vfyFvxitIiTqCkj4lcDUU0aki9EpsKDBt9K-RQ9sddqcpV9L3Y2wT0PeBeXRbVj25fCc7WOrSod0qQHDcIz3PHs4RiHfRENg2lm-ZwpuTHIBQolKqn3_oLUcUTAS9LkzodtZ_0eqPOvp1izfT3e46laRZxFQ-AcNNvSGm8rvwbQoQaICTTw",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwiYXRpIjoiZDBjMDM0ZGUtNGI2OS00NWE2LTgyMmYtNDU5MTA4NDllYzFlIiwiZXhwIjoxNjAwNjMwNTYyLCJqdGkiOiIwMDM3ZDgzNS1jNDQ4LTQ2MjktYjYxNi0yY2Y0NWQ0NDFjNzciLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSJ9.WBLLpmQ4ScekpQ7SjMrLqEtvUr2NXO1H-WVs13GK1LqBcUUrP-Qbz144itjraT6Bckw2gebojbbljQ-nze3ubS--d9zQkQL6y3cqUn7KNfTPmxIK-BXQ3QD5Rb7SMP4fX4IgeGE77uELHOXN9zCu4_Er7wX7-IhkllwBicOWP7FiXi5UIVDpf380NnWBwXlxugGI5DhW40ON50wdTnkvjmMZozRYgOO8LqejB6MKj4zX9hMoRs3eM6y2eXKj3spWiRr4e0oRZwx9m9X-0DB499hCWd6CQtxgIq4c5b6dZjNAw9XXrego9xQqcdRbKSLhbvK5fVXbt9KhEV6tqVic9A",
    "expires_in": 43199,
    "scope": "app",
    "jti": "d0c034de-4b69-45a6-822f-45910849ec1e"
}

获取令牌【密码模式】

密码模式与授权码模式的区别是申请令牌不再使用授权码,而是直接通过用户名和密码即可申请令牌,一般用于内部系统之间,进行授权访问。

申请令牌:

Post请求:
http://localhost:9200/oauth/token

【header】
clinet_id:客户端名
client_secret:客户端密码

【body】
携带参数:
grant_type:密码模式授权填写password
username:账号
password:密码

结果:
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYwMDYzMjk1MCwiYXV0aG9yaXRpZXMiOlsic2Vja2lsbF9saXN0IiwiZ29vZHNfbGlzdCJdLCJqdGkiOiIzZTEzOGMzNS0xZjUzLTQ0YzMtYTMyMC04MTc1MWI2ZDllYTYiLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSIsInVzZXJuYW1lIjoiaXRoZWltYSJ9.utWFXzdHT2DhiHEozbqv61MubL96rWg_V4evU1dG4Pq-33nYXZ1wTi5XBvYiLDzwCroVr69B5nwx21VoiG3cz2QCyVyeyS2k3iRX8mXMWJcaa_1ojjKyLLHpqWJ0Xerr1OIOaN-RLJm2Wlu4InSyTUgxCOdDXYD43g2o37nL51b3wBkQrRtLs_qMwIuj6a4oM2gW53iY0mN84Hw4AAD2UBFPJ6Mhix-Ip1DsSqavDPG3Do2WJrfu78q_O6b_UP9SaO7fuURj6szoSbqmqKudze-AWy15Gpeemz2WIt0_0jB4nO5U7Xr6aGjRseN9wivhaIfbz4vHquUJog7z0zdE0g",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwiYXRpIjoiM2UxMzhjMzUtMWY1My00NGMzLWEzMjAtODE3NTFiNmQ5ZWE2IiwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYwMDYzMjk1MCwiYXV0aG9yaXRpZXMiOlsic2Vja2lsbF9saXN0IiwiZ29vZHNfbGlzdCJdLCJqdGkiOiJkNmFjOGNiYS1hNmM1LTRhOTQtOWMzYy0yMzFmMmY4MjgyNTEiLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSIsInVzZXJuYW1lIjoiaXRoZWltYSJ9.R5jNy3-z1vg1a2gJBionUwUVDMC6Ig6hagUePIiIvovBayO72UTJX46LOBi0T6ORbF3Z5n3CFRH4cBw6LtOv1h7y2VZyYMKFtJEPzrfZe-KmqIMo0n9B1Mc9qoEH-AOOKzFSOcrtzU6qTgsgc_YrrthC-5srsg8UB4XDkahRDIytCu48zn0PNXL8I961kMNaI-s426Fo2nm_-yWDqktbQi1nrtFg37QrvO4oBBHYHj0Zf0sSshqGV25uKjAelGpzO95-7paW9cOBK2ue3GBP-RKFfUnSvCX_HZj6pZX8DnoIAEb1EbT0tuWT8zYmwKWpXzNAW12rQj7pMPIYjq6NGw",
    "expires_in": 43199,
    "scope": "app",
    "jti": "3e138c35-1f53-44c3-a320-81751b6d9ea6"
}

资源服务授权(服务对接)

资源服务拥有要访问的受保护资源,客户携带令牌访问资源服务,如果令牌合法则可以成功访问资源服务中的服务。

流程图:

Oauth2入门

  1. 客户端请求认证服务申请令牌
  2. 认证服务生成令牌认证服务采用非对称加密算法,使用私钥生成令牌。
  3. 客户端携带令牌访问资源服务客户端在Http header中添加:Authorization: Bearer令牌。
  4. 资源服务请求认证服务校验令牌的有效性资源服务接收到令牌,使用公钥校验令牌的合法性。
  5. 令牌有效,资源服务向客户端响应资源信息

步骤:

  1. 导入依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-oauth2</artifactId>
            </dependency>
    
  2. 配置每个系统的Http请求路径安全控制策略以及读取公钥信息识别令牌,如下:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    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.provider.token.TokenStore;
    import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.stream.Collectors;
    
    @Configuration
    @EnableResourceServer
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//**方法上的PreAuthorize注解
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
        //公钥
        private static final String PUBLIC_KEY = "public.key";
    
        /***
         * 定义JwtTokenStore
         * @param jwtAccessTokenConverter
         * @return
         */
        @Bean
        public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
            return new JwtTokenStore(jwtAccessTokenConverter);
        }
    
        /***
         * 定义JJwtAccessTokenConverter
         * @return
         */
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setVerifierKey(getPubKey());
            return converter;
        }
        /**
         * 获取非对称加密公钥 Key
         * @return 公钥 Key
         */
        private String getPubKey() {
            Resource resource = new ClassPathResource(PUBLIC_KEY);
            try {
                InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
                BufferedReader br = new BufferedReader(inputStreamReader);
                return br.lines().collect(Collectors.joining("\n"));
            } catch (IOException ioe) {
                return null;
            }
        }
    
        /***
         * Http安全配置,对每个到达系统的http请求链接进行校验
         * @param http
         * @throws Exception
         */
        @Override
        public void configure(HttpSecurity http) throws Exception {
            //所有请求必须认证通过
            http.authorizeRequests()
                    //下边的路径放行
                    .antMatchers(
                            "/user/add","/user/load/**"). //配置地址放行
                    permitAll()
                    .anyRequest().
                    authenticated();    //其他地址需要认证授权
        }
    }
    
    
  3. 测试

    不带令牌测试:localhost:9005/user

    返回错误信息:

    {
     "error": "unauthorized",
     "error_description": "Full authentication is required to access this
    resource"
    }
    

    带令牌测试,返回正确信息:

    {
        "flag": true,
        "code": 20000,
        "message": "查询成功",
        "data": [
        {
        	...
        }
    
相关标签: jwt oauth

上一篇:

下一篇: