我一开始用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;
}
}
tokenStore类:
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>