SpringBoot+SpringSecurity+Oauth2认证基础版

目录

1、依赖

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.11.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

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

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

        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.4.4.RELEASE</version>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2、SecurityConfig核心配置

在这里插入代码片@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	//使用内存方式创建用户
        auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("123")).roles("ADMIN");
        auth.inMemoryAuthentication().withUser("test").password(passwordEncoder.encode("123")).roles("test");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/goods/list").access("hasAnyAuthority('ROLE_ADMIN','ROLE_test')");
        http.authorizeRequests().antMatchers("/goods/add").access("hasAnyAuthority('ROLE_ADMIN')");
        http.authorizeRequests().antMatchers("/goods/update").access("hasAnyAuthority('ROLE_ADMIN')");
        http.authorizeRequests().antMatchers("/goods/delete").access("hasAnyAuthority('ROLE_ADMIN')");
        //这里要放行oauth2请求路径
        http.authorizeRequests().antMatchers("/oauth/**").permitAll();
        http.formLogin().and().logout().logoutSuccessUrl("/logout");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {

    }
}

3、 Oauth2认证服务器配置

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private static final String RESOURCE_ID = "my-resource";

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    	//基于内存
        clients.inMemory()
                //client1允许client_credentials认证
                .withClient("client1")
                .secret(passwordEncoder.encode("client1_secret"))
                .resourceIds(ResourceServerConfig.RESOURCE_ID)
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("access_token")
                .authorities("client")
                .and()
                //client2允许密码认证
                .withClient("client2")
                .secret(passwordEncoder.encode("client2_secret"))
                .resourceIds(ResourceServerConfig.RESOURCE_ID)
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("access_token")
                .authorities("client");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                .authenticationManager(authenticationManager)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持OAUTH相关接口以GET和POST方法请求
    }

    /**
     * 支持请求的时候,已表单的形式发送数据
     * @param oauthServer
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
    }
}

4、 Oauth2资源服务器配置

/**
 * @author zhe.xiao
 * @date 2021-03-26 15:35
 * @description
 * Oauth2 第二步 配置资源服务器
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    public static final String RESOURCE_ID = "my-resource";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

        resources.resourceId(RESOURCE_ID).stateless(true);
    }
}

5、编写Controller接口测试


@RestController
@RequestMapping("/goods")
public class GoodsController {

    @GetMapping("/list")
    public String list(){
        return "商品列表";
    }



    @GetMapping("/add")
    public String add(){
        return "添加商品成功";
    }


    @GetMapping("/update")
    public String update(){
        return "修改商品成功";
    }


    @GetMapping("/delete")
    public String delete(){
        return "删除商品成功";
    }
}

6、测试结果:

6.1、client_credentials认证:

请求路径: http://localhost:9101/oauth/token

参数:
grant_type :client_credentials
scope :access_token
client_id :client1
client_secret :client1_secret
SpringBoot+SpringSecurity+Oauth2认证基础版

6.2 密码认证:

请求路径: http://localhost:9101/oauth/token

参数:
grant_type :password
scope :access_token
client_id :client2
client_secret :client2_secret
username :admin
password:123
SpringBoot+SpringSecurity+Oauth2认证基础版

因为我们上面tokenStore指明的这些数据存在Redis里面,所以可以发现在生成token后redis自动新增了许多key
SpringBoot+SpringSecurity+Oauth2认证基础版

6.3 检查token是否合法

请求路径:http://localhost:9101/oauth/check_token?token=81bf3d0f-fce0-4c97-9ea7-a2a859869d7d

SpringBoot+SpringSecurity+Oauth2认证基础版

6.4 通过token访问controller

没带token:

SpringBoot+SpringSecurity+Oauth2认证基础版

token失效

SpringBoot+SpringSecurity+Oauth2认证基础版

token正确:

SpringBoot+SpringSecurity+Oauth2认证基础版

上一篇:Day07 包机制与JavaDoc


下一篇:第八天 2021.08.26