spring security oauth2

package com.example.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
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.redis.RedisTokenStore;

@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 {
            // @formatter:off
            http
                    // Since we want the protected resources to be accessible in the UI as well we need
                    // session creation to be allowed (it's disabled by default in 2.0.6)
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)

                    .and()
                    .requestMatchers()
                    .anyRequest()

                    .and()
                    .anonymous()

                    .and()
                    .authorizeRequests()
//                    .antMatchers("/product/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")
                    .antMatchers("/private/**")//配置访问控制,必须认证过后才可以访问
                    .authenticated();
            // @formatter:on
        }
    }

    // oauth 2 配置信息
    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        AuthenticationManager authenticationManager;
        @Autowired
        RedisConnectionFactory redisConnectionFactory;
        @Autowired
        private BCryptPasswordEncoder bCryptPasswordEncoder;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            //配置两个客户端,模拟第三方应用
            clients.inMemory()
                    // 凭证方式 , 适用于没有前端的命令行应用
                    .withClient("client_1")
                    .resourceIds(DEMO_RESOURCE_ID)
                    .authorizedGrantTypes("client_credentials", "refresh_token")
                    .scopes("select")
                    .authorities("client")
                    .secret(bCryptPasswordEncoder.encode("123"))

                    // 密码的方式去认证
                    .and().withClient("client_2")
                    .resourceIds(DEMO_RESOURCE_ID)
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("select")//作用域(Scopes): 客户请求访问令牌时,有资源拥有者额外指定的细分权限(permission)
                    .authorities("client")
                    .secret(bCryptPasswordEncoder.encode("123"));
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    // token 的保存方式
                    .tokenStore(new RedisTokenStore(redisConnectionFactory))
                    // 允许 GET、POST 请求获取 token,即访问端点:oauth/token
                    .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
                    //token里加点信息
//                    .tokenEnhancer(tokenEnhancerChain)
                    .authenticationManager(authenticationManager);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            //允许表单认证
            oauthServer.allowFormAuthenticationForClients();
        }

    }
}
package com.example.oauth.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.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.provisioning.InMemoryUserDetailsManager;

/**
 * @Description: spring security配置
 * @Author: yanhonghai
 * @Date: 2019/4/18 0:38
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 对应密码模式,内存中新建2个用户;实际用数据库查询
     *
     * @return
     */
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        // 内存 , 实现了登录的接口
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("zhangsan")
                .password(this.passwordEncoder().encode("123"))
                .authorities("client")
                .build());
        manager.createUser(User.withUsername("user_2")
                .password(this.passwordEncoder().encode("123"))
                .authorities("USER")
                .build());
        return manager;
    }
    // http 请求的权限配置 , 和 路径, 和 处理器
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .requestMatchers()
            .anyRequest()
            .and()
            .authorizeRequests()
            .antMatchers("/oauth/*")
            .permitAll();//生产token的url允许任何登录的用户访问
        // @formatter:on
    }
    // 鉴权管理器
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    // 加密器
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
package com.example.oauth.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;



/**
* 1.测试需要启动redis,
* 2.直接get访问localhost:8080/public/1  localhost:8080/private/1
* 3.使用http工具post访问password模式
* http://localhost:8080/oauth/token?username=zhangsan&password=123&grant_type=password&scope=select&client_id=client_2&client_secret=123
* 使用http工具post访问client模式http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123
* 4.再次get访问http://localhost:8080/private/1?access_token=bd77315b-5f83-433f-a4aa-b9f20b89ff34
* http://localhost:8080/private/1?access_token=d6912dd2-347d-4e64-98a3-922380dab7a0
* @author chentong
* @date 2021/12/1
*/
@RestController
public class TestController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping("/public/{id}")
    public String getProduct(@PathVariable String id) {
        logger.info("当前用户认证信息:{}", SecurityContextHolder.getContext().getAuthentication());
        return "public id: " + id;
    }

    @GetMapping("/private/{id}")
    public String getOrder(@PathVariable String id) {
        logger.info("当前用户认证信息:{}", SecurityContextHolder.getContext().getAuthentication());
        return "private id: " + id;
    }

}

@EnableResourceServer
@SpringBootApplication
public class OauthApplication {

    public static void main(String[] args) {
        SpringApplication.run(OauthApplication.class, args);
    }

}

spring.redis.host=localhost
spring.redis.database=0
spring.redis.port=6379
spring.redis.password=123456
#filter ����˳��,�������,���ز���
security.oauth2.resource.filter-order=3
logging.level.org.springframework.security: DEBUG

server.port=8083
readme
1.测试需要启动redis

2.直接get访问
    localhost:8080/public/1    这个路径能通过  
    localhost:8080/private/1   这个路径不放行,需要认证

3.使用http工具post访问password模式
    http://localhost:8080/oauth/token?username=zhangsan&password=123&grant_type=password&scope=select&client_id=client_2&client_secret=123456

使用http工具post访问client模式
    http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456

4.再次带上获取的tokenget访问 , get 请求
    http://localhost:8080/private/1?access_token=bd77315b-5f83-433f-a4aa-b9f20b89ff34
或者
    http://localhost:8080/private/1?access_token=d6912dd2-347d-4e64-98a3-922380dab7a0

这里的token 是上面任意种方式获取的 token
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值