/*
* Copyright 2015-2016 http://hsweb.me
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hsweb.web.oauth2.service;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.hsweb.web.bean.common.DeleteParam;
import org.hsweb.web.bean.common.InsertParam;
import org.hsweb.web.bean.common.QueryParam;
import org.hsweb.web.bean.common.UpdateParam;
import org.hsweb.web.bean.po.user.User;
import org.hsweb.web.core.exception.AuthorizeException;
import org.hsweb.web.core.exception.NotFoundException;
import org.hsweb.web.oauth2.dao.OAuth2AccessMapper;
import org.hsweb.web.oauth2.exception.AccessTimeoutException;
import org.hsweb.web.oauth2.po.OAuth2Access;
import org.hsweb.web.service.config.ConfigService;
import org.hsweb.web.service.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Service("oAuth2Service")
public class OAuth2ServiceImpl implements OAuth2Service {
@Resource
private OAuth2AccessMapper oAuth2AccessMapper;
@Resource
private UserService userService;
@Resource
private ConfigService configService;
@Autowired(required = false)
private CacheManager cacheManager;
static final String cacheName = "hsweb.oauth2";
@Override
public void addAccessToken(OAuth2Access auth2Access) {
if (auth2Access.getId() == null) {
auth2Access.setId(OAuth2Access.createUID());
}
// TODO: 16-8-17 保存n分钟再删除
//删除旧的token
List<OAuth2Access> accesses = oAuth2AccessMapper.select(QueryParam.build().where("userId", auth2Access.getUserId()));
if (accesses.size() > 0) {
accesses.forEach(this::removeAccessFromCache);
oAuth2AccessMapper.delete(DeleteParam.build().where("userId", auth2Access.getUserId()));
}
oAuth2AccessMapper.insert(InsertParam.build(auth2Access));
}
private void removeAccessFromCache(OAuth2Access auth2Access) {
//移除旧的缓存
if (cacheManager != null) {
String cacheKey = "accessToken:".concat(auth2Access.getAccessToken());
Cache cache = cacheManager.getCache(cacheName);
cache.evict(cacheKey);
}
}
@Override
public void refreshToken(OAuth2Access auth2Access) {
auth2Access.setCreateDate(new Date());
OAuth2Access old = oAuth2AccessMapper.selectByRefreshToken(auth2Access.getRefreshToken());
if (old == null) {
throw new NotFoundException("refreshToken不存在");
}
//修改
oAuth2AccessMapper.update(UpdateParam.build(auth2Access)
.includes("accessToken", "expireIn", "createDate")
.where("refreshToken", auth2Access.getRefreshToken()));
//移除旧的缓存
removeAccessFromCache(old);
}
@Override
@Transactional(noRollbackFor = {AccessTimeoutException.class, AuthorizeException.class})
public User getUserByAccessToken(String accessToken) {
OAuth2Access auth2Access = null;
Cache cache = null;
String cacheKey = "accessToken:".concat(accessToken);
boolean inCache = false;
if (cacheManager != null) {
cache = cacheManager.getCache(cacheName);
if (cache != null) {
Cache.ValueWrapper wrapper = cache.get(cacheKey);
if (wrapper != null) {
auth2Access = (OAuth2Access) wrapper.get();
inCache = true;
}
}
}
if (auth2Access == null)
auth2Access = oAuth2AccessMapper.selectByAccessToken(accessToken);
if (auth2Access == null) {
return null;
}
//判断是否已超时
if (auth2Access.getLeftTime() <= 0) {
if (cache != null) {
cache.evict(cacheKey);
}
// TODO: 16-8-17 token删除还是刷新时更新?
oAuth2AccessMapper.deleteById(auth2Access.getId());
throw new AuthorizeException("expired_token");
}
if (!inCache) {
User user = userService.selectByPk(auth2Access.getUserId());
user.initRoleInfo();
user.setPassword(null);
User newUser = new User();
try {
BeanUtilsBean.getInstance().getPropertyUtils()
.copyProperties(newUser, user);
} catch (Exception e) {
}
auth2Access.setUser(newUser);
cache.put(cacheKey, auth2Access);
return newUser;
} else {
return auth2Access.getUser();
}
}
@Override
public int getDefaultExpireIn() {
return configService.getInt("oauth2", "expire_in", 3600);
}
}