代码结构
org.springframework.boot
spring-boot-starter-security
org.springframework.cloud
spring-cloud-starter-oauth2
org.springframework.security
spring-security-test
test
com.alibaba
druid-spring-boot-starter
1.1.22
mysql
mysql-connector-java
8.0.17
org.springframework.boot
spring-boot-starter-jdbc
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
2、编写配置类
1、令牌配置类
package team.lcf.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.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
public class AccessTokenConfig {
private String SINGING_KEY = "czz";
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// 设置秘钥
// todo 后面改成非对称加密
converter.setSigningKey(SINGING_KEY);
System.out.println("--------" + SINGING_KEY);
return converter;
}
}
2、认证服务器配置(注意这里如果指定数据库模式,需要依赖spring-boot-starter-jdbc)
package team.lcf.config;
import org.springframework.beans.factory.annotation.Autowired;
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.bcrypt.BCryptPasswordEncoder;
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.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import javax.sql.DataSource;
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
UserDetailsService userDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
public AuthorizationCodeServices authorizationCodeServices;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()") // /oauth/token_key 是公开的
.checkTokenAccess("permitAll()") // /oauth/check_token公开
.allowFormAuthenticationForClients(); // 表单认证
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager) // 认证管理器
.userDetailsService(userDetailsService) // 用户信息
.authorizationCodeServices(authorizationCodeServices) // 授权码管理器
.tokenServices(tokenServices()) // 令牌管理服务
.allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET)
.pathMapping("/oauth/token","/login"); // 这里自定义获取令牌路径
}
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
//客户端端配置策略
services.setClientDetailsService(clientDetailsService);
//支持令牌的刷新
services.setSupportRefreshToken(true);
//令牌服务
services.setTokenStore(tokenStore);
//access_token的过期时间
services.setAccessTokenValiditySeconds(60 * 60 * 2);
//refresh_token的过期时间
services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
//设置令牌增强,使用JwtAccessTokenConverter进行转换
services.setTokenEnhancer(jwtAccessTokenConverter);
return services;
}
@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource) {
ClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
((JdbcClientDetailsService) jdbcClientDetailsService).setPasswordEncoder(passwordEncoder);
return jdbcClientDetailsService;
}
}
3、配置SpringSecurity管理器
package team.lcf.config;
import com.fasterxml.jackson.databind.ObjectMapper;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
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.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import team.lcf.filter.LoginFilter;
import team.lcf.pub.RespBean;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public Boolean hideUserNotFoundExceptions() {
return false;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// TODO 这里之后要重新配置,参照FrameUser
http.antMatcher("/oauth
@Service
public class UserServiceImpl implements UserDetailsService {
@Autowired
private BeanHelper beanHelper;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
FrameUser user = beanHelper.getBean(FrameUserMapper.class).loadUserByUsername(userName);
if (user == null) {
throw new GeneralException(ErrorCode.FILE_ANALYSE_ERROR);
}
Integer userId = user.getUserId();
List roles = beanHelper.getBean(FrameUserMapper.class).selectRoleByUserId(userId);
user.setRoles(roles);
return (UserDetails) user;
}
}
效果
注意:
认证服务如果选择数据库模式,需要配置固定的几张表
官网地址: https://github.com/spring-projects/spring-security-oauth/blob/main/spring-security-oauth2/src/test/resources/schema.sql
我这里记录一下我自己的sql:
CREATE TABLE oauth_client_details(
client_id VARCHAr(128) NOT NULL COMMENT '客户端ID' ,
resource_ids VARCHAr(128) COMMENT '用户ID 客户端额能访问的ID资源集合,多个使用逗号隔开' ,
client_secret VARCHAr(128) COMMENT '客户端密码 客户端的访问密钥' ,
scope VARCHAr(128) COMMENT '范围 客户端的可选权限范围,read,write,trust,多个权限范围使用逗号隔开' ,
authorized_grant_types VARCHAr(128) COMMENT '授权类型' ,
web_server_redirect_uri VARCHAr(128) COMMENT '重定向url' ,
authorities VARCHAr(128) COMMENT '当前' ,
access_token_validity BIGINT COMMENT 'token令牌有效性' ,
refresh_token_validity BIGINT COMMENT 'token刷新' ,
additional_information VARCHAr(512) COMMENT '附加信息' ,
autoapprove VARCHAr(32) COMMENT '自动续约' ,
ext1 VARCHAr(32) COMMENT 'ext1' ,
PRIMARY KEY (client_id)
) COMMENT = '客户端明细信息 保存 Oauth2客户端账号密码、授权、回调地址等';
insert into `oauth_client_details` (`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `ext1`) values('password','rid','$2a$10$r9gQOnCC77KBiHUGY0RZh.39ZPJs3lfgF6bMY7wksXzywWO6rX44O','ALL','authorization_code,implicit,client_credentials,password,refresh_token',NULL,NULL,NULL,NULL,NULL,NULL,NULL);
CREATE TABLE oauth_code(
code INT COMMENT '验证码' ,
authentication VARCHAr(128) COMMENT '身份验证' ,
ext1 VARCHAr(32) COMMENT 'ext1'
) COMMENT = '授权码 存储授权码';



