提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
本章节是帮助我们快速上手使用 Spring 提供的 Spring Security OAuth2 搭建一套验证授权及资源访问服务,帮助大家实现企业微服务架构时能够有效的控制多个服务的统一登录、授权及资源保护工作。
server-gitee:https://gitee.com/golden-Kingdragon/springsecurity-oauth2-server-demo.git
client-gitee:https://gitee.com/golden-Kingdragon/springsecurity-oauth2-client-demo.git
提示:以下是本篇文章正文内容,下面案例可供参考
先引入maven依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
<version>2.3.12.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.security.oauthgroupId>
<artifactId>spring-security-oauth2artifactId>
<version>2.3.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-jwtartifactId>
<version>1.0.9.RELEASEversion>
dependency>
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import java.util.Arrays;
@Configuration
@EnableAuthorizationServer// 这个注解告诉 Spring 这个应用是 OAuth2 的授权服务器
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// @Autowired
// private JwtTokenConfig.CustomJwtTokenEnhancer customJwtTokenEnhancer;
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
//jwt配置
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");//表单认证(申请令牌)
;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//使用内存存储client凭证,可根据情况改用jdbc存储
clients.inMemory()
.withClient("along")
.secret(passwordEncoder.encode("code"))
.authorizedGrantTypes("authorization_code","client_credentials","password","implicit","refresh_token")
.scopes("all")
.redirectUris("http://127.0.0.1:8081/code")
.accessTokenValiditySeconds(7200);
}
//jwtTokenStore存储
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.authorizationCodeServices(authorizationCodeServices);
//将增强的token设置到增强链中
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
// enhancerChain.setTokenEnhancers(Arrays.asList(customJwtTokenEnhancer, jwtAccessTokenConverter));//添加额外信息
enhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
endpoints.tokenStore(tokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
.tokenEnhancer(enhancerChain);
}
}
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
public class JwtTokenConfig {
// @Component("customJwtTokenEnhancer")
// public class CustomJwtTokenEnhancer implements TokenEnhancer {
//实现TokenEhancer(令牌增强器)中的 ehance方法,增加额外的信息
// @Override
// public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
// //token增强逻辑,务必确保保存的信息基本不变
// Map additionalInfo = new HashMap<>();
// //可以获取到代表当前用户的信息
// Object userAuthentication = authentication.getPrincipal();
// additionalInfo.put("Info", "value");
Object userAuthentication = authentication.getPrincipal();
// ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
// return accessToken;
// }
// }
@Bean
public TokenStore tokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("alongcode");
return jwtAccessTokenConverter;
}
}
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public AuthorizationCodeServices authorizationCodeServices(){
return new InMemoryAuthorizationCodeServices();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
// 设置添加用户信息,正常应该从数据库中读取
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
userDetailsService.createUser(User.withUsername("user1")
.password(passwordEncoder().encode("123456"))
.authorities("ROLE_USER1").build());
userDetailsService.createUser(User.withUsername("user2")
.password(passwordEncoder().encode("123456"))
.authorities("ROLE_USER2").build());
return userDetailsService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**","/login/**","/logout/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.and()
.csrf()
.disable();
}
}
http://127.0.0.1:8080/oauth/authorize?response_type=token&client_id=along&redirect_uri=http://127.0.0.1:8081/code&scope=all
http://127.0.0.1:8080/oauth/authorize?response_type=code&client_id=along&scope=all&redirect_uri=http://127.0.0.1:8081/code
先引入maven依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-oauth2-clientartifactId>
<version>2.6.10version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
server:
port: 8081
spring:
security:
oauth2:
client:
registration:
alongcode:
client-id: along
client-secret: code
authorization-grant-type: authorization_code
redirect-uri: 'http://127.0.0.1:8081/code'
client-name: alongcode
github:
client-id: asfasfasgw312d
client-secret: afasfsafasfasfafasf
provider:
alongcode:
authorization-uri: http://localhost:8080/oauth/authorize
token-uri: http://localhost:8080/oauth/token
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(a -> a
.antMatchers("/code/**", "/login", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login();
}
}
package com.example.demo.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.security.Principal;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(Principal principal) {
// return "Hello," + principal.getName();
return "Hello,aa";
}
@GetMapping("/code")
public ResponseEntity<String> code(String code) {
// return "Hello," + principal.getName();
System.out.println(code);
RestTemplate restTemplate = new RestTemplate();
String access_token_url = "http://localhost:8080/oauth/token";
MultiValueMap<String, Object> hashMap = new LinkedMultiValueMap<>();
hashMap.add("grant_type","authorization_code");
hashMap.add("code",code);
hashMap.add("client_id","along");
hashMap.add("client_secret","code");
hashMap.add("redirect_uri","http://127.0.0.1:8081/code");
ResponseEntity<String> responseEntity = restTemplate.postForEntity(access_token_url, hashMap, String.class);
return responseEntity;
}
}
启动认证服务器和客户端
浏览器访问:http://localhost:8081/hello
登录
同意授权
得到token
拿到token之后就可以完成自己的逻辑
没有总结。