Spring Security + Oauth2实现认证服务器
程序员文章站
2022-06-13 20:13:59
...
Spring Security + Oauth2+JWT实现认证服务器
一、依赖
<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>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 切面编程 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
二、安全配置
/**
* @Author: fxx
* @Date: 2020/5/16 8:52
* web安全配置
*/
@Configuration
@EnableWebSecurity
public class DcSecurityConfig extends WebSecurityConfigurerAdapter {
//这个是password模式需要用到的一个bean
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
//加密
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//下面url放行
.antMatchers("/oauth/**", "/sign", "/test").permitAll()
//任何请求都要认证
.anyRequest().authenticated()
.and()
//关闭csrf防护
.csrf().disable();
}
}
三、认证服务器配置
/**
* @Author: fxx
* @Date: 2020/5/15 16:36
* 认证服务器配置
*/
@Configuration
@EnableAuthorizationServer
public class DcAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
@Qualifier("userServiceImpl")
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
//token存储
@Autowired
@Qualifier("jwtTokenStore")
private TokenStore tokenStore;
//jwt令牌部分
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
//写一个token增强器到token增强里
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> enhancers = new ArrayList<>();
enhancers.add(jwtTokenEnhancer);
enhancers.add(jwtAccessTokenConverter);
tokenEnhancerChain.setTokenEnhancers(enhancers);
endpoints
.tokenEnhancer(tokenEnhancerChain)
.accessTokenConverter(jwtAccessTokenConverter);
}
//配置允许哪些应用可以访问服务器
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")//clientId
.secret(passwordEncoder.encode("secret"))//clientSecret
.accessTokenValiditySeconds(7200)//token过期时间
.authorizedGrantTypes("refresh_token", "password")//允许的认证模式:刷新token和密码模式
.scopes("all")//访问的域
.redirectUris("http://localhost:8083");//回调地址
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
//允许/oauth/check_token被访问,默认不允许访问
security.checkTokenAccess("permitAll()");
}
}
四、token存储
/**
* @Author: fxx
* @Date: 2020/5/20 10:27
* token存储
*/
@Configuration
public class TokenStoreConfig {
@Configuration
public static class JwtTokenConfig{
/**
* token存储,存储在jwt里
* @return
*/
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* token生成
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
//设置密签
accessTokenConverter.setSigningKey("secret");
return accessTokenConverter;
}
/**
* 注册jwt增强器
*/
@Bean
public TokenEnhancer jwtTokenEnhancer(){
return new HzudcJwtTokenEnhancer();
}
}
}
五、jwt附加信息
/**
* @Author: fxx
* @Date: 2020/5/20 10:33
*/
public class DcJwtTokenEnhancer implements TokenEnhancer {
@Autowired
private UserService userService;
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String, Object> info = new HashMap<>();
info.put("phone", "12345678912");
//设置附加信息
((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(info);
return oAuth2AccessToken;
}
}
六、自定义token返回格式
/**
* @Author: fxx
* @Date: 2020/5/25 14:15
* 通过切面拿到/oauth/token的返回值,做增强处理
*/
@Component
@Aspect
public class AuthTokenAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
@Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleTokenControllerMethod(ProceedingJoinPoint pjp) throws Throwable{
logger.info("/oauth/token执行前");
//调用目标方法
Object proceed = pjp.proceed();
logger.info("/oauth/token执行后");
//自定义的返回类
Result result = new Result();
if (proceed != null){
//ResponseEntity<OAuth2AccessToken>是方法的默认返回类型
ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>)proceed;
//用debug看可以看到body里是jwt信息
OAuth2AccessToken body = responseEntity.getBody();
//成功返回
if (responseEntity.getStatusCode().is2xxSuccessful()) {
result.setCode(200);
result.setMessage("登录成功");
result.add("token", body);
} else {
logger.error("error:", responseEntity.getStatusCode().toString());
result.setCode(100);
result.setMessage("用户名密码错误!");
}
}
return ResponseEntity
.status(200)
.body(result);
}
}
七、结果
八、参考
自定义token返回格式部分参考自:
上一篇: 手机建站大有文章
推荐阅读
-
Spring Security OAuth2集成短信验证码登录以及第三方登录
-
spring security 5.x实现兼容多种密码的加密方式
-
详解Spring Boot实战之Filter实现使用JWT进行接口认证
-
Spring Security认证提供程序示例详解
-
3行代码快速实现Spring Boot Oauth2服务功能
-
Spring Security OAuth2集成短信验证码登录以及第三方登录
-
Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器
-
spring security 5.x实现兼容多种密码的加密方式
-
详解Spring Boot实战之Filter实现使用JWT进行接口认证
-
spring boot 2 集成JWT实现api接口认证