1.Oauth2 相關Maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
2.Oauth2 使用的表(表明固定)OAUTH_CLIENT_DETAILS
CREATE TABLE "OAUTH_CLIENT_DETAILS"
( "CLIENT_ID" VARCHAR2(256 BYTE) NOT NULL ENABLE,
"RESOURCE_IDS" VARCHAR2(256 BYTE) DEFAULT NULL,
"CLIENT_SECRET" VARCHAR2(256 BYTE) DEFAULT NULL,
"SCOPE" VARCHAR2(256 BYTE) DEFAULT NULL,
"AUTHORIZED_GRANT_TYPES" VARCHAR2(256 BYTE) DEFAULT NULL,
"WEB_SERVER_REDIRECT_URI" VARCHAR2(256 BYTE) DEFAULT NULL,
"AUTHORITIES" VARCHAR2(256 BYTE) DEFAULT NULL,
"ACCESS_TOKEN_VALIDITY" NUMBER(11,0) DEFAULT NULL,
"REFRESH_TOKEN_VALIDITY" NUMBER(11,0) DEFAULT NULL,
"ADDITIONAL_INFORMATION" VARCHAR2(1000 BYTE) DEFAULT NULL,
"AUTOAPPROVE" VARCHAR2(256 BYTE) DEFAULT NULL,
PRIMARY KEY ("CLIENT_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 5242880 NEXT 5242880 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "LOG_DATA" ENABLE
)
3.Oauth2相關配置文件
a.token自定義載荷
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JwtTokenEnhancer implements TokenEnhancer {
private static final Logger logger = LoggerFactory.getLogger(JwtTokenEnhancer.class);
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken,
OAuth2Authentication oAuth2Authentication) {
Map<String,Object> info = new HashMap<>();
info.put("provider","Fant.J");
//设置附加信息
((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(info);
logger.debug("debug");
return oAuth2AccessToken;
}
}
b.授權服務器配置
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import com.foxconn.provider.service.MyUserDetailsService;
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
private static final Logger logger = LoggerFactory.getLogger(MyAuthorizationServerConfig.class);
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
//数据源会自动配置
@Autowired
private DataSource dataSource;
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// super.configure(security);
security.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')")
.checkTokenAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(jdbcClientDetailsService());
}
/**
* 配置通過 數據庫的方式 去 獲取 client 信息
* @return
*/
@Bean
public ClientDetailsService jdbcClientDetailsService(){
JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
return jdbcClientDetailsService;
}
//把上面的各个组件组合在一起
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.authenticationManager(authenticationManager) // 认证管理器 - 在密码模式必须配置
.userDetailsService(userDetailsService) // 自定义校验用户service
.accessTokenConverter(jwtAccessTokenConverter);
logger.debug("debug");
}
}
c.使用JWT令牌配置
@Configuration
public class TokenConfig {
/** JWT密钥 */
private String signingKey = "fastboot";
/**
* 配置 token 如何生成
* 1. InMemoryTokenStore 基于内存存储
* 2. JdbcTokenStore 基于数据库存储
* 3. JwtTokenStore 使用 JWT 存储 该方式可以让资源服务器自己校验令牌的有效性而不必远程连接认证服务器再进行认证
*/
public String getSigningKey() {
return signingKey;
}
public void setSigningKey(String signingKey) {
this.signingKey = signingKey;
}
// 第二個 token config 類
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* token生成处理:指定签名
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
accessTokenConverter.setSigningKey(signingKey);
accessTokenConverter.setVerifierKey(signingKey);
return accessTokenConverter;
}
@Bean
public TokenEnhancer jwtTokenEnhancer(){
return new JwtTokenEnhancer();
}
}
d.權限配置
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private MyUserDetailsService myuserDetailsService;
/// 自己的 數據庫實現的 用戶詳情信息
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
///auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
auth.userDetailsService(myuserDetailsService).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.and()
.authorizeRequests().antMatchers("/oauth/**").permitAll()
.anyRequest()
.authenticated()
.and().csrf().disable().cors();
}
/**
* 密碼的 加密方式
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 密碼模式下必須注入的bean authenticationManagerBean
* 認證是由 AuthenticationManager 來管理的,
* 但是真正進行認證的是 AuthenticationManager 中定義的AuthenticationProvider。
* AuthenticationManager 中可以定義有多個 AuthenticationProvider
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
4.生成token、刷新token、校驗token