spring security oauth2 自定义实现令牌存储

原创 2012年01月25日 12:34:04

我一开始用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>



版权声明:本文为博主原创文章,未经博主允许不得转载。

Failed to receive access token原因

在做一个新项目的时候 突然发现新浪认证不能用了  出现Failed to receive access token 经过查实 原来是2013年8月份以后的一些应用 (有些可以继续用 有些不能...
  • junjieking
  • junjieking
  • 2014年05月04日 17:05
  • 2873

请务必注意 Redis 安全配置,否则将导致轻松被入侵

一、前言 前段时间,在做内网影响程度评估的时候写了扫描利用小脚本, 扫描后统计发现,内网中60%开放了redis6379端口的主机处于可以被利用的危险状态,因为都是一些默认配置造成的 考虑到...
  • wuli2496
  • wuli2496
  • 2015年12月16日 17:13
  • 1980

OAuth2.0 Password接入说明

1.OAuth服务端需要引入pom com.whty whty-framework-oauth 2.项目必须配置redis,配置文件为cache.cfg 在需要进行OAuth权限校验...
  • zh350229319
  • zh350229319
  • 2016年08月22日 10:50
  • 3127

RESTful登录设计(基于Spring及Redis的Token鉴权)

什么是REST REST(Representational State Transfer)是一种软件架构风格。它将服务端的信息和功能等所有事物统称为资源,客户端的请求实际就是对资源进行操作,它的...
  • gebitan505
  • gebitan505
  • 2016年06月08日 17:59
  • 39512

OAuth2.0验证 和 SSO验证 详细

一、OAuth2.0授权协议 一种安全的登陆协议,用户提交的账户密码不提交到本APP,而是提交到授权服务器,待服务器确认后,返回本APP一个访问令牌,本APP即可用该访问令牌访问资源服务器的资源。由...
  • sinat_34990639
  • sinat_34990639
  • 2016年09月09日 20:41
  • 603

spring security oauth2 jwt 认证和资源分离的配置文件(java类配置版)

最近再学习spring security oauth2。下载了官方的例子sparklr2和tonr2进行学习。但是例子里包含的东西太多,不知道最简单最主要的配置有哪些。所以决定自己尝试搭建简单版本的例...
  • u010139801
  • u010139801
  • 2017年03月30日 10:37
  • 4481

Spring Security TokenStore实现3+1详解

TokenStore:Persistence interface for OAuth2 tokens.(对于OAuth2令牌持久化接口) 官方文档 TokenStore 的默认实现有三种:...
  • DuShiWoDeCuo
  • DuShiWoDeCuo
  • 2017年12月29日 11:03
  • 137

spring security oauth2 使用redis存token时报错

spring boot升到2.0.0.M7后,集成了spring security oauth2,redis,用redis来存储token。请求token时报错。nested exception is...
  • smollsnail
  • smollsnail
  • 2018年01月02日 17:58
  • 51

springboot+Oauth2源码的BUG——重写源码DefaultTokenServices

事实上,任何代码都有或多或少的缺陷,世界上根本就没有完美的代码,包括各种我们常用的工具包。Oauth2的源码配置中就是遇到了这样的问题。 或许是最初的设计有问题,每种手机APP的客户端都是共用了一套...
  • huhanguang89
  • huhanguang89
  • 2017年05月26日 20:34
  • 1086

Spring Security 与 Oauth2 整合 步骤

为什么要写 1. spring-security-oauth2的demo 不容易让开发者理解, 配置的内容很多, 没有分解的步骤; 我曾经试着按照文档(https://github.com/sprin...
  • monkeyking1987
  • monkeyking1987
  • 2013年11月19日 22:31
  • 111995
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:spring security oauth2 自定义实现令牌存储
举报原因:
原因补充:

(最多只允许输入30个字)