9.Spring Security Oauth2-- SSO单点登录

1.单点登录简介

  • 单点登录(Single Sign On)指的是当有多个系统需要登录时,用户只需登录一个系统,就可以访问其他需要登录的系统而无需登录。

2.创建client模块

– 这里我们创建一个security-clientt服务作为需要登录的客户端服务,使用上一节中的oauth2-jwt-server服务作为认证服务,当我们在security-server服务上登录以后,就可以直接访问security-client需要登录的接口,来演示下单点登录功能。

2.1 pom.xml依赖:

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

2.2 application配置


server:
  port: 8777
  servlet:
    session:
      cookie:
        name: OAUTH2-CLIENT-SESSIONID #防止Cookie冲突,冲突会导致登录验证不通过
# 这里填127... 后面测试时浏览器也输入127...
oauth2-server-url: http://127.0.0.1:8666
spring:
  application:
    name: security-client
security:
  oauth2:
    client:
      client-id: admin
      client-secret: admin123456
      user-authorization-uri: ${oauth2-server-url}/oauth/authorize
      access-token-uri: ${oauth2-server-url}/oauth/token
      id: admin1
      grant-type: password
      scope: all
    resource:
      token-info-uri: ${oauth2-server-url}/oauth/check_token
      # jwt 的配置
      jwt:
        key-uri: ${oauth2-server-url}/oauth/token_key
  # user-info-uri 与 token-info-uri
  #作用:二者皆是为了check token  user-info-uri: http://localhost:9005/user

2.3 @EnableOAuth2Sso启用单点登录功能

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;

@EnableOAuth2Sso
@SpringBootApplication
public class SecurityClientApplication {

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

2.4 添加接口用于获取当前登录用户信息

import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController @RequestMapping("/user")
public class UserController {

    @GetMapping("/getCurrentUser")
    //    @PreAuthorize("hasRole('admin')")
    // Authentication 别引错,不然收不到值
    public WebResponse getCurrentUser(Authentication authentication) {
        return new WebResponse("Y",authentication,"返回");
    }
}

3.修改认证服务器

owner:
  redirectUri: http://127.0.0.1:8777/login
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Value("${owner.redirectUri}")
    private String redirectUris;

    // 改为JWT
    @Resource(name = "jwtTokenStore")
    private TokenStore tokenStore;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("admin")//配置client_id
            .secret(passwordEncoder.encode("admin123456"))//配置client_secret
            .accessTokenValiditySeconds(3600)//配置访问token的有效期
            .refreshTokenValiditySeconds(8640)//配置刷新token的有效期
            .redirectUris(redirectUris)//配置redirect_uri,用于授权成功后跳转 单点登录时配置
            .scopes("all") // 配置申请的权限范围,授权页面会显示
            //.autoApprove(true) //自动授权配置
            .authorizedGrantTypes("authorization_code","password","refresh_token");//配置grant_type,表示授权类型
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        // 获取密钥需要身份认证,使用单点登录时必须配置, 默认为全部拒绝 permitAll() isAuthenticated() denyAll()
        security.tokenKeyAccess("isAuthenticated()");//.checkTokenAccess("isAuthenticated()");
    }

    // 使用密码模式需要配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
            // 设置为redis 配置令牌存储策略
            .tokenStore(tokenStore)
        // 转为jwt格式
         .accessTokenConverter(jwtAccessTokenConverter);
    }
}

4.测试

4.1 网页版

  • 访问客户端需要授权的接口http://127.0.0.1:8777/user/getCurrentUser会跳转到授权服务的登录界面;
    登录
  • 进行授权

授权

  • 授权后会跳转到原来需要权限的接口地址,展示登录用户信息
    在这里插入图片描述

4.2 Postman来演示

  • 这里我们使用Postman来演示下如何使用正确的方式调用需要登录的客户端接口。

这里开启自动授权,AuthorizationServerConfig 中的.autoApprove(true) //自动授权配置

  • 访问客户端需要登录的接口:http://127.0.0.1:8777/user/getCurrentUser
  • 使用Oauth2认证方式获取访问令牌:
    在这里插入图片描述
    在这里插入图片描述
  • 点击request_token,t跳到登录页
    在这里插入图片描述
  • 登录完成获取到令牌

在这里插入图片描述

  • 使用这个token,然后发送请求

在这里插入图片描述

  • 得到返回

在这里插入图片描述

5.security-client权限校验

5.1 开启基于方法的权限校验

@Configuration
// @EnableGlobalMethodSecurity(prePostEnabled = true) 开启后,Spring Security 的 @PreAuthorize,@PostAuthorize 注解才可以使用。
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(101)
public class SecurityConfig
    extends WebSecurityConfigurerAdapter {
    /*@Override
    public void configure(HttpSecurity http) throws Exception {

        http
            .csrf().disable()
            // 基于token,所以不需要session
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .anyRequest().authenticated();
    }*/
}

5.2 添加需要admin权限的接口

@RestController @RequestMapping("/user")
public class UserController {

    @GetMapping("/getCurrentUser")
    //    @PreAuthorize("hasRole('admin')")
    // Authentication 别引错,不然收不到值
    public WebResponse getCurrentUser(Authentication authentication) {
        return new WebResponse("Y",authentication,"返回");
    }

    @GetMapping("/adminAuth")
    @PreAuthorize("hasAuthority('admin')")
    public WebResponse adminAuth() {
        return new WebResponse("y","可以的");
    }
}

5.3 测试

  • 访问需要admin权限的接口:http://127.0.0.1:8777/user/adminAuth
  • 使用admin账户

访问
在这里插入图片描述

  • 使用user 账户

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值