SpringBoot整合Oauth2开放平台接口授权案例

<!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- springboot整合freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <!-->spring-boot 整合security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- spring-cloud-starter-oauth2 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

二、授权中心案例代码

Oauth2相关配置:

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description: 配置授权中心信息
 * @date 2020-05-03 13:21
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    /**
     * accessToken有效期 两小时
     */
    private int accessTokenValiditySeconds = 7200;

    /**
     * refreshToken有效期 两小时
     */
    private int refreshTokenValiditySeconds = 7200;

    /**
     * 添加商户信息
     *
     * @param clients 商户
     * @throws Exception 异常
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //商户id
                .withClient("client_1")
                //商户secret
                .secret(passwordEncoder().encode("123456"))
                //回调地址
                .redirectUris("https://www.baidu.com/")
                /* OAuth2为我们提供了四种授权方式:
                 * 1、授权码模式(authorization code)用在客户端与服务端应用之间授权
                 * 2、简化模式(implicit)用在移动app或者web app(这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)
                 * 3、密码模式(resource owner password credentials)应用直接都是受信任的(都是由一家公司开发的)
                 * 4、客户端模式(client credentials)用在应用API访问
                 */
                .authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code")
                //授权范围
                .scopes("all")
                //accessToken有效期
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                //refreshToken有效期
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds);
    }

    /**
     * 设置token类型
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager())
                .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
        endpoints.authenticationManager(authenticationManager());
        endpoints.userDetailsService(userDetailsService());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        // 允许表单认证
        oauthServer.allowFormAuthenticationForClients();
        // 允许check_token访问
        oauthServer.checkTokenAccess("permitAll()");
    }

    @Bean
    AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                return daoAuhthenticationProvider().authenticate(authentication);
            }

        };
        return authenticationManager;
    }

    @Bean
    public AuthenticationProvider daoAuhthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }

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

    /**
     * 设置加密方式
     *
     * @return PasswordEncoder
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Security相关配置:

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description: 添加Security权限配置
 * @date 2020-05-03 13:59
 */
@Component
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    /**
     *  授权中心管理器
     * @return AuthenticationManager
     * @throws Exception 异常
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

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

    /**
     *  拦截所有请求,使用httpBasic方式登陆
     * @param http 请求
     * @throws Exception 异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
    }

}

测试授权码模式:

访问http://localhost:8080/oauth/authorize?response_type=code&client_id=client_1&redirect_uri=https://www.baidu.com/

使用该授权码获取accessToken:

访问http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client_1&client_secret=123456&code=EwaTib&redirect_uri=https://www.baidu.com/&scope=all

测试密码模式获取accessToken:

三、受保护应用端案例代码

全局配置:

server:
  port: 8081

logging:
  level:
    org.springframework.security: DEBUG

security:
  oauth2:
    resource:
      ####从认证授权中心上验证token
      tokenInfoUri: http://localhost:8080/oauth/check_token
      preferTokenInfo: true
    client:
      accessTokenUri: http://localhost:8080/oauth/token
      userAuthorizationUri: http://localhost:8080/oauth/authorize
      ###appid
      clientId: client_1
      ###appSecret
      clientSecret: 123456

资源拦截配置:

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description: 资源拦截配置
 * @date 2020-05-03 15:43
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 对 api/order 请求进行拦截
        http.authorizeRequests().antMatchers("/api/test/**").authenticated();
    }

}

资源服务请求测试类:

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description:
 * @date 2020-05-03 15:44
 */
@RestController
@RequestMapping("/api/test")
public class TestController {

    @RequestMapping("/add")
    public String addOrder() {
        return "add success!";
    }

 启动类开启Oauth2

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description:
 * @date 2020-05-03 15:42
 */
@SpringBootApplication
@EnableOAuth2Sso
public class TestOauth2Server {
    public static void main(String[] args) {
        SpringApplication.run(TestOauth2Server.class,args);
    }
}

四、授权中心和受保护应用端联合测试

1)、没授权时:

2)、授权时:

先获取token

再用token访问资源

五、修改授权中心改成动态数据库查询的方式

下载官方数据库脚本:spring-security-oauth/schema.sql at main · spring-attic/spring-security-oauth · GitHub

新增数据库依赖:

       <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
spring:
  datasource:
    hikari:
      connection-test-query: SELECT 1
      minimum-idle: 1
      maximum-pool-size: 5
      pool-name: dbcp1
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zhq_test_oauth?autoReconnect=true&useSSL=false
    username: root
    password: root

 修改Oauth2配置:

/**
 * @author Mr.Zheng
 * @Program: parent
 * @Description: 配置授权中心信息
 * @date 2020-05-03 13:21
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {


    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;


    /**
     * accessToken有效期 两小时
     */
    private int accessTokenValiditySeconds = 7200;

    /**
     * refreshToken有效期 两小时
     */
    private int refreshTokenValiditySeconds = 7200;

    @Bean
    public TokenStore tokenStore() {
        // return new InMemoryTokenStore(); //使用内存中的 token store
        return new JdbcTokenStore(dataSource); /// 使用Jdbctoken store
    }


    /**
     * 添加商户信息
     *
     * @param clients 商户
     * @throws Exception 异常
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource)
                //测试首次运行可以指定测试数据,如果数据库中没有则不报错,如果有或者第二次运行会报错,因为数据库已经存在了,需要注释掉
                .withClient("client_1")
                //商户secret
                .secret(passwordEncoder().encode("123456"))
                //回调地址
                .redirectUris("https://www.baidu.com/")
                /* OAuth2为我们提供了四种授权方式:
                 * 1、授权码模式(authorization code)用在客户端与服务端应用之间授权
                 * 2、简化模式(implicit)用在移动app或者web app(这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)
                 * 3、密码模式(resource owner password credentials)应用直接都是受信任的(都是由一家公司开发的)
                 * 4、客户端模式(client credentials)用在应用API访问
                 */
                .authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code")
                //授权范围
                .scopes("all")
                //accessToken有效期
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                //refreshToken有效期
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds);
    }

    /**
     * 设置token类型
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager())
                .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
        endpoints.authenticationManager(authenticationManager());
        endpoints.userDetailsService(userDetailsService());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        // 允许表单认证
        oauthServer.allowFormAuthenticationForClients();
        // 允许check_token访问
        oauthServer.checkTokenAccess("permitAll()");
    }

    @Bean
    AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                return daoAuhthenticationProvider().authenticate(authentication);
            }

        };
        return authenticationManager;
    }

    @Bean
    public AuthenticationProvider daoAuhthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }

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

    /**
     * 设置加密方式
     *
     * @return PasswordEncoder
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

测试运行:

检查数据库发现测试商户已经导入到数据库了

Spring Boot整合OAuth2可以实现用户认证和授权功能。OAuth2是一种授权框架,常用于保护API端点和限制对用户数据的访问。 下面是一个简单的示例演示了如何在Spring Boot整合OAuth2: 1. 添加Spring Security和OAuth2依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 2. 创建一个配置类用于配置OAuth2: ```java @Configuration @EnableWebSecurity public class OAuth2Config extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/").permitAll() .anyRequest().authenticated() .and() .oauth2Login(); } } ``` 在上面的配置中,`configure()`方法配置了HTTP请求的权限规则,`.oauth2Login()`方法启用了OAuth2登录功能。 3. 添加OAuth2客户端配置到application.properties文件: ```properties spring.security.oauth2.client.registration.google.client-id=your-client-id spring.security.oauth2.client.registration.google.client-secret=your-client-secret spring.security.oauth2.client.registration.google.redirect-uri={baseUrl}/{action}/oauth2/code/{registrationId} spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/auth spring.security.oauth2.client.provider.google.token-uri=https://accounts.google.com/o/oauth2/token spring.security.oauth2.client.provider.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo spring.security.oauth2.client.provider.google.user-name-attribute=email ``` 上述配置使用了Google作为OAuth2的提供者,你需要替换成自己的客户端ID和客户端密钥。 4. 创建一个控制器用于处理登录成功后的回调: ```java @Controller public class OAuth2LoginController { @GetMapping("/oauth2/login/success") public String loginSuccess() { return "redirect:/"; } } ``` 在上述控制器中,`loginSuccess()`方法处理登录成功后的回调,并重定向到首页。 这只是一个简单的示例,你可以根据自己的需求进行更多的配置和定制化。希望对你有帮助!如果还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值