优秀的编程知识分享平台

网站首页 > 技术文章 正文

如何实现单点登录 ?(如何实现单点登录功能)

nanyue 2024-08-08 19:00:33 技术文章 16 ℃

作 者:微云

来 源:weyunx.com/2019/02/12/spring-boot-sso/

>>学习资源项目源码点击领取<<

Overview

最近在弄单点登录,踩了不少坑,所以记录一下,做了个简单的例子。

目标:认证服务器认证后获取 token,客户端访问资源时带上 token 进行安全验证。

可以直接看源码。

关键依赖

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> <relativePath/></parent>

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

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.1.2.RELEASE</version> </dependency></dependencies>

认证服务器

认证服务器的关键代码有如下几个文件:

AuthServerApplication:

@SpringBootApplication@EnableResourceServerpublic class AuthServerApplication { public static void main(String[] args) { SpringApplication.run(AuthServerApplication.class, args); }

}

AuthorizationServerConfiguration 认证配置:

@Configuration@EnableAuthorizationServerclass AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired AuthenticationManager authenticationManager;

@Autowired TokenStore tokenStore;

@Autowired BCryptPasswordEncoder encoder;

@Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients .inMemory .withClient("client") .secret(encoder.encode("123456")).resourceIds("hi") .authorizedGrantTypes("password","refresh_token") .scopes("read"); }

@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(tokenStore) .authenticationManager(authenticationManager); }

@Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer .allowFormAuthenticationForClients .checkTokenAccess("permitAll") .tokenKeyAccess("permitAll"); }}

代码中配置了一个 client,id 是 client,密码123456authorizedGrantTypespasswordrefresh_token两种方式。

SecurityConfiguration安全配置:

@Configuration@EnableWebSecuritypublic class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean public TokenStore tokenStore { return new InMemoryTokenStore; }

@Bean public BCryptPasswordEncoder encoder { return new BCryptPasswordEncoder; }

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication .passwordEncoder(encoder) .withUser("user_1").password(encoder.encode("123456")).roles("USER") .and .withUser("user_2").password(encoder.encode("123456")).roles("ADMIN"); }

@Override protected void configure(HttpSecurity http) throws Exception { http.csrf.disable .requestMatchers .antMatchers("/oauth/authorize") .and .authorizeRequests .anyRequest.authenticated .and .formLogin.permitAll; }

@Override @Bean public AuthenticationManager authenticationManagerBean throws Exception { return super.authenticationManagerBean; }}

上面在内存中创建了两个用户,角色分别是 USERADMIN。后续可考虑在数据库或者 Redis 中存储相关信息。

AuthUser配置获取用户信息的 Controller:

@RestControllerpublic class AuthUser { @GetMapping("/oauth/user") public Principal user(Principal principal) { return principal; }}

application.yml配置,主要就是配置个端口号:

spring: profiles: active: dev application: name: auth-serverserver: port: 8101

客户端配置

客户端的配置比较简单,主要代码结构如下:

application.yml配置:

spring: profiles: active: dev application: name: client

server: port: 8102security: oauth2: client: client-id: client client-secret: 123456 access-token-uri: http: user-authorization-uri: http: scope: read use-current-uri: false resource: user-info-uri: http:

这里主要是配置了认证服务器的相关地址以及客户端的 id 和 密码。user-info-uri配置的就是服务器端获取用户信息的接口。

HelloController访问的资源,配置了ADMIN的角色才可以访问:

@RestControllerpublic class HelloController { @RequestMapping("/hi") @PreAuthorize("hasRole('ADMIN')") public ResponseEntity<String> hi { return ResponseEntity.ok.body("auth success!"); }}

WebSecurityConfiguration相关安全配置:

@Configuration@EnableOAuth2Sso@EnableGlobalMethodSecurity(prePostEnabled = true) class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

http.csrf.disable.sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and .authorizeRequests .anyRequest.authenticated; }}

其中 @EnableGlobalMethodSecurity(prePostEnabled = true)开启后,Spring Security 的@PreAuthorize,@PostAuthorize注解才可以使用。

@EnableOAuth2Sso配置了单点登录。

ClientApplication

@SpringBootApplication@EnableResourceServerpublic class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); }}

验证

启动项目后,我们使用 postman 来进行验证。

首先是获取 token:

选择 POST提交,地址为验证服务器的地址,参数中输入username,password,grant_typescope,其中grant_type需要输入password

然后在下面等 Authorization 标签页中,选择 Basic Auth,然后输入 client 的 id 和 password。

{ "access_token": "02f501a9-c482-46d4-a455-bf79a0e0e728", "token_type": "bearer", "refresh_token": "0e62dddc-4f51-4cb5-81c3-5383fddbb81b", "expires_in": 41741, "scope": "read"}

此时就可以获得 access_token为:02f501a9-c482-46d4-a455-bf79a0e0e728。需要注意的是这里是用user_2获取的 token,即角色是ADMIN

然后我们再进行获取资源的验证:

使用 GET方法,参数中输入 access_token,值输入02f501a9-c482-46d4-a455-bf79a0e0e728

点击提交后即可获取到结果。

如果我们不加上 token ,则会提示无权限。同样如果我们换上 user_1获取的 token,因 user_1 的角色是USER,此资源需要ADMIN权限,则此处还是会获取失败。

简单的例子就到这,后续有时间再加上其它功能吧,谢谢~

干货文章,求转发!

1.12 分钟搞懂 静(动)态代理

2. Python 3 入门 ,看这篇就够了 !

3. Spring Boot 实现前后端分离、权限控制

4.学习资源、项目源码免费下载

↓ 点在看,无Bug

Tags:

最近发表
标签列表