我一开始用oauth2 for spring security的JdbcTokenStore存储令牌,它用jdbcTemplate操作数据库,代码显示操作成功,但是数据库里就是没有存储的令牌,调试搞了一天,就是找不到原因,无奈,只好自己用mybatis实现了一个tokenStore。
数据库表结构:
drop table if exists oauth_client_details; drop table if exists oauth_access_token; drop table if exists oauth_refresh_token; drop table if exists oauth_code; create table oauth_client_details ( client_id VARCHAR(50) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256) ); create table oauth_access_token ( token_id VARCHAR(256), token blob, authentication_id VARCHAR(256), authentication blob, refresh_token VARCHAR(256) ); create table oauth_refresh_token ( token_id VARCHAR(256), token blob, authentication blob ); create table oauth_code ( code VARCHAR(256), authentication blob ); insert into oauth_client_details(client_id,resource_ids,client_secret,scope,authorized_grant_types,authorities) values('client','sparklr','secret','read,write','authorization_code','ROLE_CLIENT');
package com.hxp.oauth.server.entity; import java.io.Serializable; public class MybatisOauth2AccessToken implements Serializable { private static final long serialVersionUID = -4232065232755289541L; private String tokenId; private byte[] token; private String authenticationId; private byte[] authentication; private String refreshToken; public String getTokenId() { return tokenId; } public void setTokenId(String tokenId) { this.tokenId = tokenId; } public byte[] getToken() { return token; } public void setToken(byte[] token) { this.token = token; } public String getAuthenticationId() { return authenticationId; } public void setAuthenticationId(String authenticationId) { this.authenticationId = authenticationId; } public byte[] getAuthentication() { return authentication; } public void setAuthentication(byte[] authentication) { this.authentication = authentication; } public String getRefreshToken() { return refreshToken; } public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } }
package com.hxp.oauth.server.entity; import java.io.Serializable; public class MybatisOauth2RefreshToken implements Serializable { private static final long serialVersionUID = 238497479380096784L; private String tokenId; private byte[] token; private byte[] authentication; public String getTokenId() { return tokenId; } public void setTokenId(String tokenId) { this.tokenId = tokenId; } public byte[] getToken() { return token; } public void setToken(byte[] token) { this.token = token; } public byte[] getAuthentication() { return authentication; } public void setAuthentication(byte[] authentication) { this.authentication = authentication; } }
package com.hxp.oauth.server.entity; import java.io.Serializable; public class MybatisOauth2Code implements Serializable { private static final long serialVersionUID = -1799776184263988216L; private String code; private byte[] authentication; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public byte[] getAuthentication() { return authentication; } public void setAuthentication(byte[] authentication) { this.authentication = authentication; } }
package com.hxp.oauth.server.store; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.util.SerializationUtils; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; import org.springframework.security.oauth2.provider.token.TokenStore; import com.hxp.oauth.server.dao.MybatisTokenDao; import com.hxp.oauth.server.entity.MybatisOauth2AccessToken; import com.hxp.oauth.server.entity.MybatisOauth2RefreshToken; public class MybatisTokenStore implements TokenStore { private static final Log LOG = LogFactory.getLog(MybatisTokenStore.class); private MybatisTokenDao mybatisTokenDao; private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { OAuth2Authentication authentication = null; try { MybatisOauth2AccessToken at=mybatisTokenDao.readAccessToken( token.getValue()); authentication = SerializationUtils.deserialize(at.getAuthentication()); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + token); } } return authentication; } public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { String refreshToken = null; if (token.getRefreshToken() != null) { refreshToken = token.getRefreshToken().getValue(); } MybatisOauth2AccessToken at=new MybatisOauth2AccessToken(); at.setTokenId(token.getValue()); at.setToken(SerializationUtils.serialize(token)); at.setAuthenticationId(authenticationKeyGenerator.extractKey(authentication)); at.setAuthentication(SerializationUtils.serialize(authentication)); at.setRefreshToken(refreshToken); mybatisTokenDao.storeAccessToken(at); } public OAuth2AccessToken readAccessToken(String tokenValue) { OAuth2AccessToken accessToken = null; try { accessToken = SerializationUtils.deserialize(mybatisTokenDao.readAccessToken(tokenValue).getToken()); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + tokenValue); } } return accessToken; } public void removeAccessToken(String tokenValue) { mybatisTokenDao.removeAccessToken(tokenValue); } public OAuth2Authentication readAuthentication(ExpiringOAuth2RefreshToken token) { OAuth2Authentication authentication = null; try { authentication = SerializationUtils.deserialize(mybatisTokenDao.readRefreshToken(token.getValue()).getAuthentication()); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + token); } } return authentication; } public void storeRefreshToken(ExpiringOAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { MybatisOauth2RefreshToken rt=new MybatisOauth2RefreshToken(); rt.setTokenId(refreshToken.getValue()); rt.setToken(SerializationUtils.serialize(refreshToken)); rt.setAuthentication(SerializationUtils.serialize(authentication)); mybatisTokenDao.storeRefreshToken(rt); } public ExpiringOAuth2RefreshToken readRefreshToken(String tokenValue) { ExpiringOAuth2RefreshToken refreshToken = null; try { refreshToken = SerializationUtils.deserialize(mybatisTokenDao.readRefreshToken(tokenValue).getToken()); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.info("Failed to find refresh token for token " + tokenValue); } } return refreshToken; } public void removeRefreshToken(String tokenValue) { mybatisTokenDao.removeRefreshToken(tokenValue); } public void removeAccessTokenUsingRefreshToken(String refreshToken) { mybatisTokenDao.removeAccessTokenUsingRefreshToken(refreshToken); } public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { OAuth2AccessToken accessToken = null; try { String auth=authenticationKeyGenerator.extractKey(authentication); MybatisOauth2AccessToken at=mybatisTokenDao.getAccessToken(auth); if(null==at){ return null; }else{ accessToken = SerializationUtils.deserialize(at.getToken()); } } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.debug("Failed to find access token for authentication " + authentication); } } return accessToken; } public MybatisTokenDao getMybatisTokenDao() { return mybatisTokenDao; } public void setMybatisTokenDao(MybatisTokenDao mybatisTokenDao) { this.mybatisTokenDao = mybatisTokenDao; } }
dao接口类:
package com.hxp.oauth.server.dao; import com.hxp.oauth.server.entity.MybatisOauth2AccessToken; import com.hxp.oauth.server.entity.MybatisOauth2RefreshToken; public interface MybatisTokenDao { void storeAccessToken(MybatisOauth2AccessToken token); MybatisOauth2AccessToken readAccessToken(String tokenValue); void removeAccessToken(String tokenValue); void storeRefreshToken(MybatisOauth2RefreshToken token); MybatisOauth2RefreshToken readRefreshToken(String tokenValue); void removeRefreshToken(String tokenValue); void removeAccessTokenUsingRefreshToken(String refreshToken); MybatisOauth2AccessToken getAccessToken(String authentication); }
mapper 配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hxp.oauth.server.dao.MybatisTokenDao"> <resultMap id="accessToken" type="com.hxp.oauth.server.entity.MybatisOauth2AccessToken"> <result property="tokenId" column="token_id" /> <result property="token" column="token" /> <result property="authenticationId" column="authentication_id" /> <result property="authentication" column="authentication" /> <result property="refreshToken" column="refresh_token" /> </resultMap> <resultMap id="refreshToken" type="com.hxp.oauth.server.entity.MybatisOauth2RefreshToken"> <result property="tokenId" column="token_id" /> <result property="token" column="token" /> <result property="authentication" column="authentication" /> </resultMap> <resultMap id="code" type="com.hxp.oauth.server.entity.MybatisOauth2Code"> <result property="code" column="code" /> <result property="authentication" column="authentication" /> </resultMap> <insert id="storeAccessToken" parameterType="com.hxp.oauth.server.entity.MybatisOauth2AccessToken"> insert into oauth_access_token (token_id, token, authentication_id, authentication, refresh_token) values (#{tokenId}, #{token ,javaType=byte[], jdbcType=BLOB,typeHandler=org.apache.ibatis.type.BlobTypeHandler}, #{authenticationId}, #{authentication ,javaType=byte[], jdbcType=BLOB,typeHandler=org.apache.ibatis.type.BlobTypeHandler}, #{refreshToken}) </insert> <select id="readAccessToken" parameterType="string" resultMap="accessToken"> select token_id, token,authentication from oauth_access_token where token_id = #{tokenValue} </select> <delete id="removeAccessToken" parameterType="string" > delete from oauth_access_token where token_id = #{tokenValue} </delete> <insert id="storeRefreshToken" parameterType="com.hxp.oauth.server.entity.MybatisOauth2RefreshToken" > insert into oauth_refresh_token (token_id, token, authentication) values (#{tokenId}, #{token ,javaType=byte[], jdbcType=BLOB,typeHandler=org.apache.ibatis.type.BlobTypeHandler}, #{authentication ,javaType=byte[], jdbcType=BLOB,typeHandler=org.apache.ibatis.type.BlobTypeHandler}) </insert> <select id="readRefreshToken" parameterType="string" resultMap="refreshToken" > select token_id, token,authentication from oauth_refresh_token where token_id = #{tokenValue} </select> <delete id="removeRefreshToken" parameterType="string" > delete from oauth_refresh_token where token_id = #{tokenValue} </delete> <delete id="removeAccessTokenUsingRefreshToken" parameterType="string" > delete from oauth_access_token where refresh_token = #{tokenValue} </delete> <select id="getAccessToken" parameterType="string" resultMap="accessToken"> select token_id, token from oauth_access_token where authentication_id = #{authentication} </select> </mapper>