温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

基于Spring Security Oauth2的SSO单点登录+JWT权限控制实践

发布时间:2020-08-17 01:58:07 来源:网络 阅读:5983 作者:Java萌新 栏目:编程语言

基于Spring Security Oauth2的SSO单点登录+JWT权限控制实践

概 述

在前文《基于Spring Security和 JWT的权限系统设计》之中已经讨论过基于 Spring Security和 JWT的权限系统用法和实践,本文则进一步实践一下基于 Spring Security Oauth3实现的多系统单点登录(SSO)和 JWT权限控制功能,毕竟这个需求也还是蛮普遍的。

代码已开源,放在文尾,需要自取
理论知识

在此之前需要学习和了解一些前置知识包括:

Spring Security:基于 Spring实现的 Web系统的认证和权限模块
OAuth3:一个关于授权(authorization)的开放网络标准
单点登录 (SSO):在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
JWT:在网络应用间传递信息的一种基于 JSON的开放标准((RFC 7519),用于作为JSON对象在不同系统之间进行安全地信息传输。主要使用场景一般是用来在 身份提供者和服务提供者间传递被认证的用户身份信息
要完成的目标

目标1:设计并实现一个第三方授权中心服务(Server),用于完成用户登录,认证和权限处理
目标2:可以在授权中心下挂载任意多个客户端应用(Client)
目标3:当用户访问客户端应用的安全页面时,会重定向到授权中心进行身份验证,认证完成后方可访问客户端应用的服务,且多个客户端应用只需要登录一次即可(谓之 “单点登录 SSO”)
基于此目标驱动,本文设计三个独立服务,分别是:

一个授权服务中心(codesheep-server)
客户端应用1(codesheep-client1)
客户端应用2(codesheep-client2)
多模块(Multi-Module)项目搭建

三个应用通过一个多模块的 Maven项目进行组织,其中项目父 pom中需要加入相关依赖如下:

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.0.8.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

    <dependency>
        <groupId>io.spring.platform</groupId>
        <artifactId>platform-bom</artifactId>
        <version>Cairo-RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Finchley.SR2</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

</dependencies>

项目结构如下:
基于Spring Security Oauth2的SSO单点登录+JWT权限控制实践

授权认证中心搭建

授权认证中心本质就是一个 Spring Boot应用,因此需要完成几个大步骤:

pom中添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth3</artifactId>
    </dependency>
</dependen

项目 yml配置文件:

server:
port: 8085
servlet:
context-path: /uac


即让授权中心服务启动在本地的 8085端口之上

创建一个带指定权限的模拟用户

@Component
public class SheepUserDetailsService implements UserDetailsService {

@Autowired
private PasswordEncoder passwordEncoder;

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

    if( !"codesheep".equals(s) )
        throw new UsernameNotFoundException("用户" + s + "不存在" );

    return new User( s, passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_NORMAL,ROLE_MEDIUM"));
}

}


这里创建了一个用户名为codesheep,密码 123456的模拟用户,并且赋予了 普通权限(ROLE_NORMAL)和 中等权限(ROLE_MEDIUM)

认证服务器配置 AuthorizationServerConfig

这里做的最重要的两件事:一是 定义了两个客户端应用的通行证(sheep1和sheep2);二是 配置 token的具体实现方式为 JWT Token。

Spring Security安全配置 SpringSecurityConfig

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

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

@Autowired
private UserDetailsService userDetailsService;

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

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    authenticationProvider.setHideUserNotFoundExceptions(false);
    return authenticationProvider;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
            .requestMatchers().antMatchers("/oauth/**","/login/**","/logout/**")
            .and()
            .authorizeRequests()
            .antMatchers("/oauth/**").authenticated()
            .and()
            .formLogin().permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider());
}

}


客户端应用创建和配置

本文创建两个客户端应用:codesheep-client1 和codesheep-client2,由于两者类似,因此只以其一为例进行讲解

SSO客户端应用配置类 ClientWebsecurityConfigurer

@Configuration@EnableWebSecurity
br/>@EnableWebSecurity
br/>@EnableOAuth3Sso

@Override
public void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/**").authorizeRequests()
            .anyRequest().authenticated();
}

}


复杂的东西都交给注解了!

application.yml配置

auth-server: http://localhost:8085/uac
server:
port: 8086

security:
oauth3:
client:
client-id: sheep1
client-secret: 123456
user-authorization-uri: ${auth-server}/oauth/authorize
access-token-uri: ${auth-server}/oauth/token
resource:
jwt:
key-uri: ${auth-server}/oauth/token_key


这里几项配置都非常重要,都是需要和前面搭建的授权中心进行通信的

创建测试控制器 TestController

@RestController
public class TestController {

@GetMapping("/normal")
@PreAuthorize("hasAuthority('ROLE_NORMAL')")
public String normal( ) {
    return "normal permission test success !!!";
}

@GetMapping("/medium")
@PreAuthorize("hasAuthority('ROLE_MEDIUM')")
public String medium() {
    return "medium permission test success !!!";
}

@GetMapping("/admin")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public String admin() {
    return "admin permission test success !!!";
}

}



此测试控制器包含三个接口,分别需要三种权限(ROLE_NORMAL、ROLE_MEDIUM、ROLE_ADMIN),待会后文会一一测试看效果

实验验证

启动授权认证中心 codesheep-server(启动于本地8085端口)
启动客户端应用 codesheep-client1 (启动于本地8086端口)
启动客户端应用 codesheep-client2 (启动于本地8087端口)
首先用浏览器访问客户端1 (codesheep-client1) 的测试接口:localhost:8086/normal,由于此时并没有过用户登录认证,因此会自动跳转到授权中心的登录认证页面:http://localhost:8085/uac/login:

![](https://s1.51cto.com/images/blog/201905/07/95f2c5660545deea5998d79ab67e831f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

![](https://s1.51cto.com/images/blog/201905/07/1110eb56499a673f4ea2edd404fa683a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

![](https://s1.51cto.com/images/blog/201905/07/9b6c8a7647900c9b1be37d085d5bfd08.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

![](https://s1.51cto.com/images/blog/201905/07/856b231c3a171270aa8fa0876f93ef3a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

这就验证了单点登录SSO的功能了!
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI