spring-security-oauth的认证流程主要分为以下几步:
1、在xml文件中配置拦截oauth认证的请求地址,如下所示
<!-- OAuth 2 Authorize-->
<!-- 拦截所有以oauth开头的请求,若访问用户没有权限,则默认跳转到/oauth/oauth_login请求中,进行登录,登录过程中进行用户名和密码等信息的匹配由
oauthAuthenticationManager认证管理器处理-->
<sec:http pattern="/oauth/**" access-denied-page="/oauth/oauth_login"
authentication-manager-ref="oauthAuthenticationManager">
<sec:intercept-url pattern="/oauth/authorize"
OAuth认证请求地址
access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<!--处理登录请求的配置 -->
<sec:form-login authentication-failure-url="/oauth/login"
登录失败的默认请求地址
default-target-url="/index"
登录成功的地址
login-page="/oauth/login"
登录请求的地址
login-processing-url="/oauth/oauthLogin.do"
点击登录按钮时的请求地址,只需将form表单的action置为此值即可,无需自己写请求处理的代码
/>
</sec:http>
<!--通过用户名和密码查询用户的认证管理器 -->
<sec:authentication-manager id="oauthAuthenticationManager">
<sec:authentication-provider ref="oauthDbAuthenticationProvider"/>
</sec:authentication-manager>
<!--真正查询数据库并进行登录验证的地方 -->
<bean id="oauthDbAuthenticationProvider" class="xxx.xx.xxx.OauthDbAuthenticationProvider" />
如果浏览器发送一个诸如如下请求地址(OAuth2.0认证时,这些参数必须存在)
/oauth/authorize?client_id=&response_type=&redirect_uri=&scope=%s请求时,首先查看xml文件中是否有配置对该请求的拦截,若有配置,则spring-security框架内部会进行处理,将请求的参数组装成一个DefaultSavedRequest对象,并以"SPRING_SECURITY_SAVED_REQUEST"为键,保存在session域中。当登录成功后,spring-security-oauth框架会根据session中是否存在DefaultSavedRequest对象而将请求发送到不同地方。如果存在DefaultSavedRequest对象,则配置的 default-target-url="/index"的值将无效,此时的目标页面将是/oauth/authorize地址。
@Controller
@SessionAttributes(types = AuthorizationRequest.class)
@RequestMapping("/oauth/authorize")
public class AuthorizationEndpoint extends AbstractEndpoint
implements InitializingBean {
@RequestMapping(params = "response_type")
public ModelAndView authorize(Map<String,Object> model,
@RequestParam("response_type")String responseType,
Code或token
@RequestParam Map<String,String> parameters,
SessionStatus sessionStatus, Principal principal) {
if(!(principal instanceof Authentication) || !((Authentication)
principal).isAuthenticated()) {
sessionStatus.setComplete();
//出现异常时,自动跳入登录页面
throw new InsufficientAuthenticationException("");
}
}
用户登录成功后,下一步就是授权
//进入用户授权页面后的请求地址
@RequestMapping(method=RequestMethod.POST,params=APPROVAL)
Public View approveOrDeny(@RequestParam(APPROVAL) boolean approved,
@ModelAttribute AuthorizationRequest authorizationRequest,
SessionStatus sessionStatus, Principal principal) {
if(authorizationRequest.getClientId() == null) {
sessionStatus.setComplete();
throw new InvalidClientException("");
}
if(!(principal instanceof Authentication)) {
sessionStatus.setComplete();
throw new InsufficientAuthenticationException("");
}
try {
Set<String> responseTypes=authorizationRequest.getResponseTypes();
authorizationRequest = resolveRedirectUri(authorizationRequest);
if(responseTypes.contains("token")) {
return getImplicitGrantResponse(authorizationRequest.approved
(true)).getView();
}
return getAuthorizationCodeResponse(authorizationRequest.approved
(approved), (Authentication) principal);
} finally {
sessionStatus.setComplete();
}
OAuth认证成功后,紧接着就是用服务器返回的code码获取accessToken对象(以response_type=code)为例。获取token的请求地址为"/oauth/token",实现类是TokenEndpoint,spring-security-oauth支持4种获取token的方式,分别为:
Password、authorization_code、refresh_token、implicit。框架会根据用户传递的grant_type值,采用对应的方式获取token。值得注意的是,获取token的方式,需在xml文件中配置,如下所示:
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="oauthAuthenticationManager"/>
</oauth:authorization-server>