初识Spring Security OAuth2(一)

1. 工程结构

1.1项目代码

pom文件设置

<project xmlns="http://maven.apache.org/POM/4.0.0"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.huangwei</groupId>

    <artifactId>oauth-demo</artifactId>

    <version>0.0.1-SNAPSHOT</version>

 

    <parent>

       <groupId>org.springframework.boot</groupId>

       <artifactId>spring-boot-starter-parent</artifactId>

       <version>2.0.7.RELEASE</version>

       <relativePath /> <!-- lookup parent from repository -->

    </parent>

 

    <dependencies>

       <!-- 注意是starter,自动配置 -->

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-security</artifactId>

       </dependency>

       <!-- 不是starter,手动配置 -->

       <dependency>

           <groupId>org.springframework.security.oauth</groupId>

           <artifactId>spring-security-oauth2</artifactId>

           <version>2.3.5.RELEASE</version>

       </dependency>

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-web</artifactId>

       </dependency>

 

    </dependencies>

 

</project>

application.yml文件设置

server:

  port: 10011

OauthApp.java文件设置

package cn.huangwei.app;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class OauthApp {

         public static void main(String[] args) {

                   SpringApplication.run(OauthApp.class, args);

         }

}

Test EndPoint.java 文件配置

package cn.huangwei.app;

 

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class TestEndpoints {

 

    @GetMapping("/product/{id}")

    public String getProduct(@PathVariable String id) {

        //for debug

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        return "product id : " + id;

    }

 

    @GetMapping("/order/{id}")

    public String getOrder(@PathVariable String id) {

        //for debug

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        return "order id : " + id;

    }

 

}

 

 

SecurityConfiguration.java文件设置

package cn.huangwei.app;

 

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.EnableWebSecurity;

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.factory.PasswordEncoderFactories;

import org.springframework.security.crypto.password.PasswordEncoder;

import org.springframework.security.provisioning.InMemoryUserDetailsManager;

 

@Configuration

@EnableWebSecurity

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

 

    @Bean

    @Override

    protected UserDetailsService userDetailsService() {

       BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

       // password 方案三:支持多种编码,通过密码的前缀区分编码方式

       String finalPassword = "{bcrypt}" + bCryptPasswordEncoder.encode("123456");

       InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(User.withUsername("user_1").password(finalPassword).authorities("USER").build());

        manager.createUser(User.withUsername("user_2").password(finalPassword).authorities("USER").build());

       return manager;

    }

 

    // password 方案三:支持多种编码,通过密码的前缀区分编码方式,推荐

    @Bean

    PasswordEncoder passwordEncoder() {

       return PasswordEncoderFactories.createDelegatingPasswordEncoder();

    }

 

    /**

     * 这一步的配置是必不可少的,否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户

     */

    @Bean

    @Override

    public AuthenticationManager authenticationManagerBean() throws Exception {

       AuthenticationManager manager = super.authenticationManagerBean();

       return manager;

    }

 

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.requestMatchers().anyRequest().and().authorizeRequests().antMatchers("/oauth/*").permitAll();

    }

}

 

Oauth2ServerConfig.java文件设置

package cn.huangwei.app;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.http.SessionCreationPolicy;

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.configuration.EnableResourceServer;

import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

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.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

 

@Configuration

public class OAuth2ServerConfig {

 

    private static final String DEMO_RESOURCE_ID = "order";

 

    @Configuration

    @EnableResourceServer

    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

 

        @Override

        public void configure(ResourceServerSecurityConfigurer resources) {

            resources.resourceId(DEMO_RESOURCE_ID).stateless(true);

        }

 

        @Override

        public void configure(HttpSecurity http) throws Exception {

            http

                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)

                    .and()

                    .requestMatchers().anyRequest()

                    .and()

                    .anonymous()

                    .and()

                    .authorizeRequests()

                    .antMatchers("/order/**").authenticated();//配置order访问控制,必须认证过后才可以访问

        }

    }

 

 

    @Configuration

    @EnableAuthorizationServer

    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

 

        @Autowired

        AuthenticationManager authenticationManager;

       

 

        @Override

        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

            //配置两个客户端,一个用于password认证一个用于client认证

             String finalSecret = "{bcrypt}"+new BCryptPasswordEncoder().encode("123456");

             //配置两个客户端,一个用于password认证一个用于client认证

             clients.inMemory().withClient("client_1")

                     .resourceIds(DEMO_RESOURCE_ID)

                     .authorizedGrantTypes("client_credentials", "refresh_token")

                     .scopes("select")

                     .authorities("oauth2")

                     .secret(finalSecret)

                     .and().withClient("client_2")

                     .resourceIds(DEMO_RESOURCE_ID)

                     .authorizedGrantTypes("password", "refresh_token")

                     .scopes("select")

                     .authorities("oauth2")

                     .secret(finalSecret);

        }

 

        @Override

        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

            endpoints

                    .tokenStore(new InMemoryTokenStore())

                    .authenticationManager(authenticationManager)

                    .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);

        }

 

        @Override

        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

            //允许表单认证

            oauthServer.allowFormAuthenticationForClients();

        }

 

    }

 

}

 

运行OauthApp工程文件,然后浏览器中输入client模式:

http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456

响应如下:

{"access_token":"fbd5a92b-39b0-4330-b195-bd5518539f41","token_type":"bearer","expires_in":42102,"scope":"select"}

 

1.2各个java 文件的作用

资源服务器OAuth2ServerConfig-ResourceServerConfiguration

使用@EnableResourceServer修饰的Configurer接口。实现此接口以调整受OAuth2安全性保护的访问规则和路径。应用程序可以提供此接口的多个实例,如果多个实例配置相同的属性,则使用最后一个配置的属性值。在应用之前,配置程序按{@link Order}排序。

该接口有两个方法

① 添加资源的相关属性

② 配置资源的安全访问规则,默认是所有在/oauth/**的资源都应该被保护

一般去继承ResourceServerConfigurerAdapter这个接口类。然后实现相关方法。

@EnableResourceServer注解自动增加了一个类型为OAuth2AuthenticationProcessin-gFilter的过滤器链

认证服务器OAuth2ServerConfig-AuthorizationServerConfiguration

使用@EnableAuthorizationServer来修饰一个类,表明认证服务器配置类。

有三个方法:

①配置客户端的相关信息,id,secret,scope等信息

②配置认证endPoint的相关信息,tokenstore类型,authenticationManager,允许生成token的request method,例如get,most等。

③配置授权服务器/oauth/token endPoint的安全性,一般采用默认规则,即使不配置也能使用,创建ClientCredentialsTokenEndpointFilter核心过滤器

TestEndpointscontroller用于验证安全访问的请求,不再赘述

SecurityConfiguration文件

配置用户的信息,以及一些需要在认证服务器中使用的bean实例,config(HttpSecurity http)用户设置哪些方法能够通行,不需要经过安全认证

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值