springsecurity Oauth2.0 + jwt 极简入门demo

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本章节是帮助我们快速上手使用 Spring 提供的 Spring Security OAuth2 搭建一套验证授权及资源访问服务,帮助大家实现企业微服务架构时能够有效的控制多个服务的统一登录、授权及资源保护工作。
server-gitee:https://gitee.com/golden-Kingdragon/springsecurity-oauth2-server-demo.git
client-gitee:https://gitee.com/golden-Kingdragon/springsecurity-oauth2-client-demo.git


提示:以下是本篇文章正文内容,下面案例可供参考

一、认证服务端搭建demo

先引入maven依赖

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
			<version>2.3.12.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security.oauth</groupId>
			<artifactId>spring-security-oauth2</artifactId>
			<version>2.3.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-jwt</artifactId>
			<version>1.0.9.RELEASE</version>
		</dependency>

1. AuthorizationServerConfig Oauth2配置类

package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
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.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import java.util.Arrays;


@Configuration
@EnableAuthorizationServer// 这个注解告诉 Spring 这个应用是 OAuth2 的授权服务器
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

//    @Autowired
//    private JwtTokenConfig.CustomJwtTokenEnhancer customJwtTokenEnhancer;

    @Autowired
    private AuthorizationCodeServices authorizationCodeServices;
    //jwt配置
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .tokenKeyAccess("permitAll()")
        .checkTokenAccess("permitAll()");//表单认证(申请令牌)
        ;

    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //使用内存存储client凭证,可根据情况改用jdbc存储
        clients.inMemory()
                .withClient("along")
                .secret(passwordEncoder.encode("code"))
                .authorizedGrantTypes("authorization_code","client_credentials","password","implicit","refresh_token")
                .scopes("all")
                .redirectUris("http://127.0.0.1:8081/code")
                .accessTokenValiditySeconds(7200);
    }

    //jwtTokenStore存储
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
        .authorizationCodeServices(authorizationCodeServices);
        //将增强的token设置到增强链中
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
//        enhancerChain.setTokenEnhancers(Arrays.asList(customJwtTokenEnhancer, jwtAccessTokenConverter));//添加额外信息
        enhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));

        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
                .tokenEnhancer(enhancerChain);
    }



}

2. JwtTokenConfig JWT配置类

package com.example.demo.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 JwtTokenConfig {

//    @Component("customJwtTokenEnhancer")
//    public class CustomJwtTokenEnhancer implements TokenEnhancer {

        //实现TokenEhancer(令牌增强器)中的 ehance方法,增加额外的信息
//        @Override
//        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
//            //token增强逻辑,务必确保保存的信息基本不变
//            Map<String, Object> additionalInfo = new HashMap<>();
//            //可以获取到代表当前用户的信息
//            Object userAuthentication = authentication.getPrincipal();
//            additionalInfo.put("Info", "value");
            Object userAuthentication = authentication.getPrincipal();

//            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
//            return accessToken;
//        }
//    }

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

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

}

3. WebSecurityConfig springsecurity配置类

package com.example.demo.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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
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.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public AuthorizationCodeServices authorizationCodeServices(){
        return new InMemoryAuthorizationCodeServices();
    }

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

    // 设置添加用户信息,正常应该从数据库中读取
    @Bean
  public   UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("user1")
                .password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER1").build());
        userDetailsService.createUser(User.withUsername("user2")
                .password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER2").build());
        return userDetailsService;
    }


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

            http.authorizeRequests()
                    .antMatchers("/oauth/**","/login/**","/logout/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .formLogin()
                    .permitAll()
                    .and()
                    .csrf()
                    .disable();

    }

}

二、四种认证模式

1. 密码模式 password

在这里插入图片描述

2. 客户端模式 client_credentials

在这里插入图片描述

3. 简化模式 Implicit

http://127.0.0.1:8080/oauth/authorize?response_type=token&client_id=along&redirect_uri=http://127.0.0.1:8081/code&scope=all

在这里插入图片描述
登录授权
在这里插入图片描述
授权之后返回token
在这里插入图片描述

4. 授权码模式 authorization_code

http://127.0.0.1:8080/oauth/authorize?response_type=code&client_id=along&scope=all&redirect_uri=http://127.0.0.1:8081/code

在这里插入图片描述
同意授权
在这里插入图片描述

在这里插入图片描述
获取token
在这里插入图片描述

三、自定义授权客户端demo

先引入maven依赖

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-client</artifactId>
			  <version>2.6.10</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

1. client配置

server:
  port: 8081
spring:
  security:
    oauth2:
      client:
        registration:
          alongcode:
            client-id: along
            client-secret: code
            authorization-grant-type: authorization_code
            redirect-uri: 'http://127.0.0.1:8081/code'
            client-name: alongcode
          github:
            client-id: asfasfasgw312d
            client-secret: afasfsafasfasfafasf
        provider:
          alongcode:
            authorization-uri: http://localhost:8080/oauth/authorize
            token-uri: http://localhost:8080/oauth/token


2. WebSecurityConfig springsecurity配置类

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(a -> a
                        .antMatchers("/code/**", "/login", "/error", "/webjars/**").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2Login();
    }
}

3. controller

package com.example.demo.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.security.Principal;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(Principal principal) {
//        return "Hello," + principal.getName();
        return "Hello,aa";
    }

    @GetMapping("/code")
    public ResponseEntity<String> code(String code) {
//        return "Hello," + principal.getName();
        System.out.println(code);
        RestTemplate restTemplate = new RestTemplate();
        String access_token_url = "http://localhost:8080/oauth/token";

        MultiValueMap<String, Object> hashMap = new LinkedMultiValueMap<>();
        hashMap.add("grant_type","authorization_code");
        hashMap.add("code",code);
        hashMap.add("client_id","along");
        hashMap.add("client_secret","code");
        hashMap.add("redirect_uri","http://127.0.0.1:8081/code");

        ResponseEntity<String> responseEntity = restTemplate.postForEntity(access_token_url, hashMap, String.class);
        return responseEntity;
    }

}

4.测试

启动认证服务器和客户端
浏览器访问:http://localhost:8081/hello
在这里插入图片描述

登录
在这里插入图片描述
同意授权
在这里插入图片描述
得到token
在这里插入图片描述
拿到token之后就可以完成自己的逻辑


总结

没有总结。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值