OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
授权使用的场景是什么呢?其实现在市面上有好多的列子,最常用的就是第三方登录。其实他们就是用oauth2来控制资源权限的授权。就比如csdn可以使用qq登录,然后获取qq上自己的信息来进行csdn的注册,省了用户访问网站动不动就要注册的麻烦。oauth2最要是通过token来验证用户的权限。基本上是围绕着token。oauth2要与security一起,一个用于认证一个用于授权。
而oauth2的主要是分了几个模式:
1、密码模式。
2、客户端模式
3、简化模式
4、授权码模式
具体的可以参考这个链接地址这里写链接内容
在进入具体模式的情况下要先弄清楚spring security 和oauth2里面的拦截器,这个我也不多讲了,自己可以百度一下(因为好多)。
废话不多说就直接上代码吧。ps(我这里是基于spring boot 和spring cloud来设计的)
一、密码模式
密码模式:其实就是将用户的用户名和密码给第三方用户,他拿到你的用户名和密码去获取相应的token。最后带着token去访问相应的接口来获取你的自己的数据。
网上好多的例子都是基于内存来实现的,就是将用户名和密码放在内存中,但是现实情况中是将token以及用户信息和第三方信息都是放在数据库进行存储的。所以我们接下来的几种模式都会基于数据库来设计。
首先我们要建立相应的数据库表,其实oauth2已经帮我们设计好了一张数据库表,你只要自己导入进行就可以了。具体怎么设计以及每张表的作用可以参考这各链接:这里写链接内容
数据库弄好了我们就可以开始弄代码了,密码模式首先你得能验证用户账号和密码是否正确吧,而这个密码和用户账号是在认证服务进行认证的,就比如在qq上的用户不可能将认证给第三方吧,oauth2的好处就是,我们以qq做例子,认证和资源都是在qq服务器进行的,而第三方客户端需要带着自己的client_id以及用户的账号和密码来获取相应的token。拿到token就相当于用户同意第三方拿取该用户的信息。不多说直接代码吧。
首先要了解几个接口:UserDetailsService(看这个名字就知道获取用户的细节)以及UserDetails这两个类,他们做的主要作用就是判断用户账号是否正确,继承UserDetailsService要实现loadUserByUsername进行判断用户账号密码是否正确,还有一个就是clientDetailsService这个主要是用于认证第三方客户端的,他要实现loadClientByClientId,其实原理和上面的一样。如下代码:
@Service("UserDetailsService")
public class AuthUserDetailsServiceImpl implements UserDetailsService {
@Autowired
private AuthUserDetailsDao authUserDetailsDao;
/**
* 获取用户信息 TODO: 加缓存
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = authUserDetailsDao.findUser(username);//查询数据库是否有改用户
if (user == null) return null;
List<Role> roles = authUserDetailsDao.findRolesByUserid(user.getId());//获取用户的相应的角色
UserRepositoryUserDetails userDetails = new UserRepositoryUserDetails(user, roles);//进行用户账号和密码的匹对
return userDetails;
}
}
而clientDetailsService的代码如下:
@Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
/**clients
.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password", "refresh_token")//有什么方式获取token
.authorities("USER")
.scopes("read", "write")//希望获得的权限
.resourceIds(RESOURCE_ID)
.secret("123456");*/这是放在内存的第三方的信息
ClientDetail clientDetail = dao.getById(clientId);
//TODO:改数据库查询
ClientDetails client = new SampleClientDetails(clientDetail);//查找是否有第三方的信息
return client;
}
这时候我们使用数据库方式的已经弄好了,这里我是使用mybatis的,具体的数据库配置我就不贴出来了。记住第三方那边一定要有密码模式(authorizedGrantTypes这个字段添加,多个用,分割)的方式,不然无法使用该模式进行访问。还有就是要重写tokenstore这个类,其实oauth2里面有持久化的实现。好像是jdbctokenstore这个类,我们自己重写生成token以及涮洗的都是仿造这个类来弄的。