springcloud集成Spring Security

1.Spring Security介绍

几乎每个信息系统都需要认证授权保障其可靠性和安全性,当我们用spring框架开发时,Spring Security是一个不错的选择。

Spring Security是一个专注于为Java应用程序提供身份认证和授权功能的强大框架。它基于Spring框架,并提供了全面的安全服务集成,包括认证(Authentication)、授权(Authorization)、攻击防护和会话管理等功能。

2.集成Spring Security

2.1部署认证服务工程

在项目中新建一个springboot工程,并创建controller类定义接口

@Slf4j
@RestController
@RequestMapping("/auth")
public class LoginController {

    @RequestMapping("/login-success")
    public String loginSuccess() {

        return "登录成功";
    }
   
    @RequestMapping("/r/r1")
    public String r1() {
        return "访问r1资源";
    }

    @RequestMapping("/r/r2")
    public String r2() {
        return "访问r2资源";
    }
}

启动服务,此时我们可以 在浏览器中访问http://localhost:63070/auth/login-successhttp://localhost:63070/auth/r/r1,结果如下

2.2导入Spring Security依赖

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

此时再次访问http://localhost:63070/auth/r/r1时,会自动进入/login登录页面,要先登录才能访问/r/r1资源。

/login是spring security提供的,加载可能较慢。

默认用户名user,每次启动服务时密码会自动重新生成并在控制台输出

3自定义用户认证授权测试

1.自定义配置类继承WebSecurityConfigurerAdapter配置类

2.通过重写 configure(HttpSecurity http) 方法来定义安全规则和访问控制。

注意:NoOpPasswordEncoder 通常用于测试或者开发环境中,因为它并不会对密码进行任何加密,而是将密码以明文的形式存储和验证。存在严重的安全风险,因为密码可以很容易地被窃取和滥用。建议不要在生产环境中使用类似的明文密码存储方式。

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public UserDetailsService userDetailsService(){
        //这里配置用户信息,这里暂时使用这种方式将用户存储在内存中
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("xiyangyang").password("123").authorities("p1").build());
        manager.createUser(User.withUsername("meiyangyang").password("456").authorities("p2").build());
        return manager;
    }

    //获取一个密码编码器对象
    @Bean
    public PasswordEncoder passwordEncoder(){
        //密码为明文方式
        return NoOpPasswordEncoder.getInstance();
    }

    //配置安全拦截机制
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests()
                .antMatchers("/r/**").authenticated()//访问/r开始的请求需要认证通过
                .anyRequest().permitAll()//其它请求全部放行
                .and()
                .formLogin().successForwardUrl("/login-success");//登录成功跳转到/login-success
        http.logout().logoutUrl("/logout");//退出地址
    }
}

此时便可以用自定义的用户名和密码登录访问服务

4.集成OAuth2

4.1OAuth2介绍

4.1.2什么是OAuth2

OAuth 2(Open Authorization 2)是一种授权框架,允许第三方应用程序通过使用授权服务器进行限制的方式,访问受保护的资源,而无需用户将其凭据直接提供给第三方应用程序。它在网络服务之间提供了安全的授权标准。

4.1.3为什么使用OAuth2

OAuth 2.0 是一个开放的标准,被广泛接受和支持。许多大型的互联网服务提供商和平台都实现了 OAuth 2.0,使得开发者可以使用统一的协议和工具来实现授权流程,而无需为每个服务提供商单独开发授权机制。我们熟知的微信扫码就是基于这种OAuth2协议实现的

4.1.4OAuth2的授权模式

Spring Security支持OAuth2认证,OAuth2提供授权码模式、密码模式、简化模式、客户端模式等授权模式,微信扫码登录就是基于授权码模式,其中授权码模式和密码模式应用较多,下面使用Spring Security演示授权码模式、密码模式

4.2导入OAuth2.0依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

4.3创建授权服务器配置类

4.3.1获取并配置 AuthenticationManager 的实例

在之前创建的WebSecurityConfig 中注入AuthenticationManager,以支持身份验证功能

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

 4.3.1创建授权服务器配置类AuthorizationServer

@EnableAuthorizationServer 注解标识并继承AuthorizationServerConfigurerAdapter来配置OAuth2.0 授权服务器

 @Configuration
 @EnableAuthorizationServer
 public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

  @Resource(name="authorizationServerTokenServicesCustom")
  private AuthorizationServerTokenServices authorizationServerTokenServices;

 @Autowired
 private AuthenticationManager authenticationManager;

  //客户端详情服务
  @Override
  public void configure(ClientDetailsServiceConfigurer clients)
          throws Exception {
        clients.inMemory()// 使用in-memory存储
                .withClient("baidu")// client_id
                .secret("baidu")//客户端密钥
//                .secret(new BCryptPasswordEncoder().encode("XcWebApp"))//客户端密钥
                .resourceIds("baidu-resource")//资源列表
                // 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")
                .scopes("all")// 允许的授权范围
                .autoApprove(false)//false跳转到授权页面
                //客户端接收授权码的重定向地址
                .redirectUris("http://www.baidu.com")
   ;
  }

  //令牌端点的访问配置
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
   endpoints
           .authenticationManager(authenticationManager)//认证管理器
           .tokenServices(authorizationServerTokenServices)//令牌管理服务
           .allowedTokenEndpointRequestMethods(HttpMethod.POST);
  }

  //令牌端点的安全配置
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security){
   security
           .tokenKeyAccess("permitAll()")                    //oauth/token_key是公开
           .checkTokenAccess("permitAll()")                  //oauth/check_token公开
           .allowFormAuthenticationForClients()				//表单认证(申请令牌)
   ;
  }

 }

 4.2新建令牌配置类

@Configuration
public class TokenConfig {

    @Autowired
    TokenStore tokenStore;

    @Bean
    public TokenStore tokenStore() {
        //使用内存存储令牌(普通令牌)
        return new InMemoryTokenStore();
    }

    //令牌管理服务
    @Bean(name="authorizationServerTokenServicesCustom")
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service=new DefaultTokenServices();
        service.setSupportRefreshToken(true);//支持刷新令牌
        service.setTokenStore(tokenStore);//令牌存储策略
        service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
        return service;
    }

}

 4.4授权码模式测试

启动服务,登录成功后在浏览器输入以下地址:

注意:我们在AuthorizationServer已经配置好了以下参数

http://localhost:63070/auth/oauth/authorize?client_id=baidu&response_type=code&scope=all&redirect_uri=http://www.baidu.com

解释: 

client_id:客户端的唯一标识符
response_type:授权码模式固定为code。
scope:客户端权限。
redirect_uri:跳转uri,当授权码申请成功后会跳转到此地址,并在后边带上code参数(授权码)

 此时会出现以下界面选择approve,点击authorize则会跳转到百度页面

我们可以看到地址为https://www.baidu.com/?code=Rd8kGZ,此时便可以拿到授权码Rd8kGZ

注意:授权码只能使用一次。

拿到授权码后,使用postman或者httpclient执行

注意更改code为=Rd8kGZ

POST localhost:63070/auth/oauth/token?client_id=baidu&client_secret=baidu&grant_type=authorization_code&code=Rd8kGZ&redirect_uri=http://www.baidu.com

此时申请令牌成功

解释:

access_token:这是一个访问令牌,用于客户端在访问受保护的资源时进行身份验证和授权。
token_type:指定了访问令牌的类型,这里是 bearer。是OAuth 2.0中定义的一种令牌类型,表示客户端可以使用令牌来访问被授权的资源。
refresh_token:刷新令牌,用于获取新的访问令牌。刷新令牌有更长的有效期,用于在访问令牌过期时获取新的访问令牌。
expires_in:
表示访问令牌的有效期限(秒)。
scope:指定了授权的范围,all 表示这个访问令牌被授予了访问所有资源的权限。

 4.5密码模式测试

密码模式相对授权码模式简单,不需要借助浏览器。

可以直接postman或者httpclient执行

POST localhost:63070/auth/oauth/token?client_id=baidu&client_secret=baidu&grant_type=password&username=xiyangyang&password=123

解释:

client_id=baidu: 这是客户端的唯一标识符。
client_secret=baidu: 客户端的密钥,用于对客户端的身份进行验证。
grant_type=password: 指定了密码授权模式。
username=xiyangyang: 用户名
password=123: 用户密码

执行输出:

注意:密码模式十分简单,但却意味着将用户敏感信息泄露给了client,建议仅在确保安全的环境下使用。

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值