原理
- 在对称加密体系中,公钥用来加密信息,私钥用来数字签名。或者说只有一个密钥 AES、DES (
比如ssh 公钥登陆,用户将自己的公钥储存在远程主机上authorized_keys , 登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell
) - 在非对称加密体系中, 要有一对密钥对 ,一个被称为私钥,一个称为公钥。把公钥分发给想给你传密文的用户,然后用户使用该公钥加密过得密文,只有使用私钥才能解密 RSA
双向认证 甲乙各自有一对公私钥 ,甲先用乙的公钥加密这段数据,再用自己的私钥加密这段加密后的数据,最后再发给乙。乙 先用甲的公钥解密,再用自己私钥解密 (这样确保了内容即不会被读取,也不会被篡改。)
.
非对称加密比对称加密的效率低,因此在实际的通信过程中一般会同时使用非对称加密和对称加密来实现数据加密传输
例如 https, 首选浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。浏览器随机生成一个用于对称加密的密钥clientAesKey,用公钥A加密后传给服务器。服务器用私钥 解密 后还原成clientAesKey , 之后双方所有数据都通过密钥clientAesKey 加密解密 ,这样是防止不了中间人攻击,因此还需要CA数字证书
现象
-
访问oauth授权的URI以启动OAuth2流程:
http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client
-
重定向到登录页面:
http://localhost:8080/server/login
-
处理批准并重定向到我配置的重定向页面,其中包含一个代码参数:
http://localhost:8080/client?code=HMJO4K
-
使用基本身份验证使用客户端ID和密码以及授权类型和代码构造GET请求:
http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K
-
作为回报接收access_token和刷新令牌对象
{
"access_token": "f853bcc5-7801-42d3-9cb8-303fc67b0453",
"token_type": "bearer",
"refresh_token": "57100377-dea9-4df0-adab-62e33f2a1b49",
"expires_in": 3600,
"scope": "read write"
}
-
尝试使用access_token访问受限资源:
http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453
-
令牌过期,再次POST到令牌uri以刷新令牌
http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49
Spring Security流程
认证
- 用户登陆,会被
AuthenticationProcessingFilter
拦截,调用AuthenticationManager
的实现, - 而
AuthenticationManager
会调用ProviderManager
来获取用户验证信息(不同的Provider调用的服务不同,因为这些信息可以是在数据库上,可以是在LDAP服务器上,可以是xml配置文件上等) - 如果验证通过后会将用户的权限信息封装一个User放到spring的全局缓存
SecurityContextHolder
中,以备后面访问资源时使用。
授权
- 访问资源,访问url时,会通过
AbstractSecurityInterceptor
拦截器拦截,其中会调用FilterInvocationSecurityMetadataSource
的方法来获取被拦截url所需的全部权限, - 再调用授权管理器
AccessDecisionManager
,这个授权管理器会通过spring的全局缓存SecurityContextHolder
获取用户的权限信息,还会获取被拦截的url和被拦截url所需的全部权限,然后根据所配的策略
–AccessDecisionManager
实现有:一票通过AffirmativeBased
,,
– 一票通过AffirmativeBased
– 一票否定UnanimousBased
– 少数服从多数ConsensusBased
等 - 再邀请
AccessDecisionVoter
投票器参与投票,如果权限足够,则返回,权限不够则报错并调用权限不足页面。
–AccessDecisionVoter
实现有
–AuthenticatedVoter
根据认证对象的级别进行投票,具体查询完整认证用户、记住我认证或匿名认证
–RoleVoter
基于任何一个以“ROLE_”开头的配置属性进行投票. 如果符合条件,则搜索认证对象的GrantedAuthority
列表.
–WebExpressionVoter
允许我们使用 SpEL (Spring Expression Language) 去授权使用@PreAuthorize注解的请求.