Springcloud+springsecurity+oauth2统一授权认证(基于内存)

Springcloud+springsecurity+oauth2微服务统一授权认证

总共搭建授权微服务、学生微服务

1.引入pom

<dependencyManagement>
        <dependencies>
            <!--spring boot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

2.授权服务器授权编写(基于内存)

@Configuration
@EnableAuthorizationServer //授权服务a1
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {


    //配置客户端详情a2
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //基于内存存储
        clients.inMemory()
                //客户端id
                .withClient("c1")
                //客户端秘钥
                .secret(new BCryptPasswordEncoder().encode("secret"))
                //可访问的资源列表
                 .resourceIds("res1")
                //客户端授权类型
                .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
                //授权范围,就是服务、读写权限等
                .scopes("all")
                //跳转到授权页面
                .autoApprove(false)
                //回调地址
                .redirectUris("http://www.baidu.com");
    }


    @Autowired
    TokenStore tokenStore;
    @Autowired
    ClientDetailsService clientDetailsService;
    // a4客户端令牌服务
    @Bean
    public AuthorizationServerTokenServices tokenServices(){
        DefaultTokenServices services=new DefaultTokenServices();
        //客户端信息服务
        services.setClientDetailsService(clientDetailsService);
        //是否产生刷新令牌
        services.setSupportRefreshToken(true);
        //令牌存储策略tokenConfig.tokenService()
        services.setTokenStore(tokenStore);
        //令牌默认有效期
        services.setAccessTokenValiditySeconds(7200);
        //刷新令牌默认有效期3天
        services.setRefreshTokenValiditySeconds(259200);
        return services;
    }
    //令牌访问端点a5

    @Autowired
    AuthorizationCodeServices authorizationCodeServices;

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
           endpoints
                   //密码模式
                   .authenticationManager(authenticationManager)
                   //授权码需要
                   .authorizationCodeServices(authorizationCodeServices)
                   //服务端
                   .tokenServices(tokenServices())
                   //允许放行请求
                   .allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET);


    }

    //令牌访问安全策略a6
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                //oatuh/token_key公开
                .tokenKeyAccess("permitAll()")
                //检验令牌oatuh/check_token
                .checkTokenAccess("permitAll()")
                //表单认证申请令牌
                .allowFormAuthenticationForClients();
    }


}

3.配置授权码存储策略、加密方式

@Configuration
public class TokenConfig {


    //a3令牌策略
    @Bean
    public TokenStore tokenService(){
        return new InMemoryTokenStore();
    }
    设置授权码模式的授权码如何 存取,这里采用内存方式
    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }

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

4.配置拦截器securi

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    //加密工具类
    @Autowired
    private BCryptPasswordEncoder bcryptPasswordEncoder;

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

    @Autowired
    private FailureHandler failureHandler;

    @Autowired
    private LogoutHandler logoutHandler;
    //安全拦截器a7
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable().formLogin()
                .loginProcessingUrl("/login").permitAll()
                .successHandler(successHandler).permitAll()
                .failureHandler(failureHandler).permitAll().and()
                .logout().logoutSuccessHandler(logoutHandler).and()
                .authorizeRequests()
                .antMatchers("/**").permitAll();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password(bcryptPasswordEncoder.encode("123456")).roles("ADMIN")
                .and()
                .withUser("user").password(bcryptPasswordEncoder.encode("123456")).roles("USER");
    }
}

5.配置启动类

@EnableDiscoveryClient
@SpringBootApplication
public class UaaApplication {

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

6.配置application.yml

server:
  port: 8500

spring:
  application:
    name: oauth-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
#暴露监控
management:
  endpoints:
    web:
      exposure:
        include: '*'

7.测试获取token,检查token,授权token

获取token post表单请求:http://127.0.0.1:8500/oauth/token 
参数:
client_id:c1
client_secret:secret
username:admin
password:123456
grant_type:password
结果:
{
    "access_token": "63ea77f9-44ad-468f-bc80-e6396e19c954",
    "token_type": "bearer",
    "refresh_token": "42caab7a-9bd6-47ff-8761-a88de1e999db",
    "expires_in": 6464,
    "scope": "all"
}
检查token get请求http://127.0.0.1:8500/oauth/check_token?token=63ea77f9-44ad-468f-bc80-e6396e19c954
结果
{
    "aud": [
        "res1"
    ],
    "user_name": "admin",
    "scope": [
        "all"
    ],
    "active": true,
    "exp": 1660125310,
    "authorities": [
        "ROLE_ADMIN"
    ],
    "client_id": "c1"
}
刷新token post请求 http://127.0.0.1:8500/oauth/token
参数:
client_id:c1
client_secret:secret
username:admin
password:123456
grant_type:password
refresh_token:63ea77f9-44ad-468f-bc80-e6396e19c954
结果
{
    "access_token": "976bbbcf-dd38-4df8-9c69-51c9d34347e9",
    "token_type": "bearer",
    "refresh_token": "8ac13f11-b9a7-47b5-99b1-61b4bf507dbf",
    "expires_in": 6893,
    "scope": "all"
}

2.搭建学生服务

1.pom

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ls.demo</groupId>
            <artifactId>demo-commom</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--授权-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

2.配置资源服务器

@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
    //资源列表
    public  static  final  String RESOURCE_ID="res1";

    //资源服务器a9
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
         resources.resourceId(RESOURCE_ID).tokenServices(tokenServices()).stateless(true);
    }
    //a11资源令牌解析服务
    @Bean
    public ResourceServerTokenServices tokenServices(){
        //使用远程请求授权服务器的方式检验token的客户端id和密码
        RemoteTokenServices services=new RemoteTokenServices();
        services.setCheckTokenEndpointUrl("http://127.0.0.1:8500/oauth/check_token");
        services.setClientId("c1");
        services.setClientSecret("secret");
        return services;
    }


    //校验授权范围a10
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**")
                .access("#oauth2.hasScope('all')")
                .and().csrf().disable()
                //不用记录session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

}

3.业务请求

@RestController
@RequestMapping("/student")
public class StudentController {


    /**
     * 老师权限或学生权限
     */
    @GetMapping("/grade")
    @PreAuthorize("hasAnyAuthority('teacher','student')")
    public Object rs(HttpServletRequest request){
        Map<String,Object> map=new HashMap<>();
        map.put("张三",100);
        return map;
    }


}

3.application.yml

server:
  port: 8000

spring:
  application:
    name: school-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

4.启动类

@SpringBootApplication
@EnableDiscoveryClient
public class SchoolApplication {

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

}

5.测试

get请求获取学生信息:http://localhost:8000/student/grade
请求头Authorization:Bearer 63ea77f9-44ad-468f-bc80-e6396e19c954
结果:
{
    "张三": 100
}

版权声明:本文为ls_636原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。