登录

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();
        }
    }

results matching ""

    No results matching ""