SpringSecurity的TokenStore四種實(shí)現(xiàn)方式小結(jié)
什么是Token Store
在Web開發(fā)中,Token Store 通常用于存儲(chǔ)用戶身份驗(yàn)證令牌(Tokens),例如 JSON Web Tokens (JWT) 或其他形式的令牌。這些令牌可以用于驗(yàn)證用戶身份,實(shí)現(xiàn)用戶會(huì)話管理以及訪問控制。
一種簡(jiǎn)單的Token Store示例,使用Node.js和Express框架以及一個(gè)基于內(nèi)存的Token存儲(chǔ)方式:
const express = require('express'); const jwt = require('jsonwebtoken'); const app = express(); app.use(express.json()); // In-memory Token Store const tokenStore = {}; // Secret key for JWT (replace with a strong, secret key in production) const secretKey = 'your_secret_key'; // Middleware to verify JWT function verifyToken(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(403).json({ message: 'No token provided' }); } jwt.verify(token, secretKey, (err, decoded) => { if (err) { return res.status(401).json({ message: 'Failed to authenticate token' }); } req.user = decoded; next(); }); } // Endpoint to generate and return a JWT app.post('/login', (req, res) => { const { username, password } = req.body; // Authenticate user (replace with your actual authentication logic) // For simplicity, assume any username and password combination is valid const user = { username, role: 'user' }; // Generate a JWT const token = jwt.sign(user, secretKey, { expiresIn: '1h' }); // Store the token in memory tokenStore[token] = user; res.json({ token }); }); // Protected endpoint that requires a valid JWT for access app.get('/protected', verifyToken, (req, res) => { res.json({ message: 'This is a protected endpoint', user: req.user }); }); // Start the server const port = 3000; app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); });
Spring Security 提供了幾個(gè)常見的
TokenStore
實(shí)現(xiàn),包括內(nèi)存中存儲(chǔ)、JDBC 數(shù)據(jù)庫存儲(chǔ)和基于 JWT(JSON Web Token)的存儲(chǔ)。下面將分別介紹這三種實(shí)現(xiàn)方式,并提供基本的代碼示例。
1. 內(nèi)存中存儲(chǔ)(In-Memory)
這個(gè)是OAuth2默認(rèn)采用的實(shí)現(xiàn)方式。在單服務(wù)上可以體現(xiàn)出很好特效(即并發(fā)量不大,并且它在失敗的時(shí)候不會(huì)進(jìn)行備份),大多項(xiàng)目都可以采用此方法。根據(jù)名字就知道了,是存儲(chǔ)在內(nèi)存中,畢竟存在內(nèi)存,而不是磁盤中,調(diào)試簡(jiǎn)易。但是,實(shí)際中很少使用,因?yàn)闆]有持久化,會(huì)導(dǎo)致數(shù)據(jù)丟失。
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Bean public TokenStore inMemoryTokenStore() { return new InMemoryTokenStore(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients .inMemory() .withClient("client") .secret("{noop}secret") // 使用 "{noop}" 表示不加密 .authorizedGrantTypes("password", "authorization_code", "refresh_token") .scopes("read", "write") .accessTokenValiditySeconds(3600) .refreshTokenValiditySeconds(86400); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(inMemoryTokenStore()) .authenticationManager(authenticationManager); } }
2. JDBC 數(shù)據(jù)庫存儲(chǔ)
這個(gè)是基于JDBC的實(shí)現(xiàn),令牌(Access Token)會(huì)保存到數(shù)據(jù)庫。這個(gè)方式,可以在多個(gè)服務(wù)之間實(shí)現(xiàn)令牌共享。因?yàn)槭潜4娴綌?shù)據(jù)庫,而且是必須有OAuth2默認(rèn)的表結(jié)構(gòu):oauth_access_token。
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private DataSource dataSource; @Bean public TokenStore jdbcTokenStore() { return new JdbcTokenStore(dataSource); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients .jdbc(dataSource); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(jdbcTokenStore()) .authenticationManager(authenticationManager); } }
3. 基于 JWT 的存儲(chǔ)
jwt全稱 JSON Web Token。這個(gè)實(shí)現(xiàn)方式不用管如何進(jìn)行存儲(chǔ)(內(nèi)存或磁盤),因?yàn)樗梢园严嚓P(guān)信息數(shù)據(jù)編碼存放在令牌里。JwtTokenStore 不會(huì)保存任何數(shù)據(jù),但是它在轉(zhuǎn)換令牌值以及授權(quán)信息方面與 DefaultTokenServices 所扮演的角色是一樣的。
既然jwt是將信息存放在令牌中,那么就得考慮其安全性,因此,OAuth2提供了JwtAccessTokenConverter實(shí)現(xiàn),添加jwtSigningKey,以此生成秘鑰,以此進(jìn)行簽名,只有jwtSigningKey才能獲取信息。
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Value("${security.jwt.client-id}") private String clientId; @Value("${security.jwt.client-secret}") private String clientSecret; @Value("${security.jwt.grant-type}") private String grantType; @Value("${security.jwt.scope-read}") private String scopeRead; @Value("${security.jwt.scope-write}") private String scopeWrite; @Value("${security.jwt.resource-ids}") private String resourceIds; @Bean public TokenStore jwtTokenStore() { return new JwtTokenStore(jwtAccessTokenConverter()); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey("secret"); return converter; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients .inMemory() .withClient(clientId) .secret("{noop}" + clientSecret) .authorizedGrantTypes(grantType) .scopes(scopeRead, scopeWrite) .resourceIds(resourceIds); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(jwtTokenStore()) .accessTokenConverter(jwtAccessTokenConverter()) .authenticationManager(authenticationManager); } }
4.RedisTokenStore
顧名思義,就是講令牌信息存儲(chǔ)到redis中。首先必須保證redis連接正常。
@Autowired private RedisConnectionFactory redisConnectionFactory; /** * redis token 配置 */ @Bean public TokenStore redisTokenStore() { return new RedisTokenStore(redisConnectionFactory); } @Autowired(required = false) private TokenStore redisTokenStore; /** * 端點(diǎn)(處理入口) */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(redisTokenStore); .... }
小結(jié)
我們介紹了Spring Security中四種不同的Token Store實(shí)現(xiàn)方式。具體包括內(nèi)存中存儲(chǔ)、JDBC數(shù)據(jù)庫存儲(chǔ)、保存到redis和基于JWT的存儲(chǔ)。每個(gè)實(shí)現(xiàn)方式都涉及到授權(quán)服務(wù)器的配置,用于管理和驗(yàn)證令牌,以及客戶端詳情的配置。
到此這篇關(guān)于SpringSecurity的TokenStore四種實(shí)現(xiàn)方式小結(jié)的文章就介紹到這了,更多相關(guān)SpringSecurity TokenStore內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于@EnableGlobalMethodSecurity注解的用法解讀
這篇文章主要介紹了關(guān)于@EnableGlobalMethodSecurity注解的用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03java json 省市級(jí)聯(lián)實(shí)例代碼
這篇文章介紹了java json 省市級(jí)聯(lián)實(shí)例代碼,有需要的朋友可以參考一下2013-09-09如何優(yōu)雅的實(shí)現(xiàn)將Collection轉(zhuǎn)為Map
這篇文章主要介紹了如何優(yōu)雅的實(shí)現(xiàn)將Collection轉(zhuǎn)為Map,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03