分布式微服务架构下的用户认证鉴权代码实现
1.前言(阅读本文章前需要先学习springsecurity、oauth2、jwt,此处只是代码实现demo,如果用于生产级代码还需要做优化)
本次采用sringsecurity、oauth2与jwt结合的方式进行用户认证、鉴权实现,其中有一个安全服务器用作请求拦截,认证服务器用作用户认证,以及持久化方式:存储方式存在redis、内存、jwt等三种方式,本词采用jwt方式,因为jwt是无状态的,可以再任何实例直接解析;
新建一个安全认证服务用来做认证鉴权,另外有一个用户服务用来做用户相关的业务,登录接口在用户服务,后面会有一个拦截器,拦截器我是自定义了一个starter导入的jar包 供服务使用
1.1代码结构
认证服务:
自定义的jar包
自定义的starter
服务依赖引入:
2.代码实现
2.1安全服务器
package com.ding.security.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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.client.RestTemplate;
/**
* 配置 security安全服务器
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.and()
//此处对oauth接口放行
.authorizeRequests().antMatchers("/oauth/**").permitAll().anyRequest().authenticated()
.and()
.logout().permitAll()
.and()
.csrf().disable().httpBasic();
}
/**
* 密码模式需要添加以下bean
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 初始化一个restTemplate,可以供远程调用使用(可以不用)
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.2 配置授权服务器
package com.ding.security.config;
import com.ding.security.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
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;
import javax.sql.DataSource;
/**
* 配置授权服务器(密码模式)
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
@Qualifier("userDetails")
private UserDetailsService userDetailsService;
@Autowired
@Qualifier("jwtTokenStore")
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
//客户端配置
@Bean