登录
Controller 中为页面 model 添加 Filter
...
...
import org.mitre.openid.connect.client.OIDCAuthenticationFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.stereotype.Controller;
@Controller
public class HomeController {
...
...
@Autowired
private OIDCAuthenticationFilter filter;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model, Principal p) {
model.addAttribute("issuerServiceClass", filter.getIssuerService().getClass().getSimpleName());
model.addAttribute("serverConfigurationServiceClass", filter.getServerConfigurationService().getClass().getSimpleName());
model.addAttribute("clientConfigurationServiceClass", filter.getClientConfigurationService().getClass().getSimpleName());
model.addAttribute("authRequestOptionsServiceClass", filter.getAuthRequestOptionsService().getClass().getSimpleName());
model.addAttribute("authRequestUriBuilderClass", filter.getAuthRequestUrlBuilder().getClass().getSimpleName());
...
return "home";
}
}
为 /user 页面添加权限认证
@RequestMapping("/user")
@PreAuthorize("hasRole('ROLE_USER')")
public String user(Principal p) {
return "user";
}
OpenID 授权成功之后, 可以从 OIDCAuthenticationToken 获身份令牌,访问令牌,用户信息 。
OIDCAuthenticationToken token = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
JWT idToken = token.getIdToken();
String accessToken = token.getAccessTokenValue();
UserInfo userInfo = token.getUserInfo();
登出
登出分为 OP 登出和 RP 登出
OP 登出
通过调用 OP 用户登出 (end_session_endpoint)API ,需要URL查询参数 id_token_hint 和 post_logout_redirect_uri
id_token_hint 值为身份令牌
post_logout_redirect_uri 为 OP 登出后回调 URI
RP 登出
只要将 post_logout_redirect_uri 设为 Spring Security Logout URL 即可, 它会在 OP 登出成功后继续登出 RP。
Spring Security Logout URL
<security:logout logout-url="/j_spring_security_logout" delete-cookies="JSESSIONID" />
Client Configuration
<bean class="org.mitre.oauth2.model.RegisteredClient">
...
...
<property name="postLogoutRedirectUris">
<set>
<value>http://localhost:8080/j_spring_security_logout</value>
</set>
</property>
</bean>
/logout
@RequestMapping("/logout")
@PreAuthorize("hasRole('ROLE_USER')")
public String logout(Principal p) {
OIDCAuthenticationToken token = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
String idToken = token.getIdToken().serialize();
String sessionEndpoint = getEndSessionEndpoint(token);
String postLogoutRedirectUri = getPostLogoutRedirectUri(token);
return "redirect:" +
sessionEndpoint +
"?id_token_hint=" + idToken +
"&post_logout_redirect_uri=" +
postLogoutRedirectUri;
}
private String getPostLogoutRedirectUri(OIDCAuthenticationToken token) {
Set<String> postLogoutRedirectUris = filter.getClientConfigurationService()
.getClientConfiguration(
filter.getServerConfigurationService().getServerConfiguration(getIssuer(token.getIdToken())))
.getPostLogoutRedirectUris();
String postLogoutRedirectUri = "";
for (String uri : postLogoutRedirectUris) {
postLogoutRedirectUri = uri;
}
return postLogoutRedirectUri;
}
private String getEndSessionEndpoint(OIDCAuthenticationToken token) {
return filter.getServerConfigurationService()
.getServerConfiguration(getIssuer(token.getIdToken()))
.getEndSessionEndpoint();
}
private String getIssuer(JWT jwt) {
try {
return jwt.getJWTClaimsSet().getIssuer();
} catch (ParseException e) {
throw new RuntimeException();
}
}