SpringBoot Security的oauth2 sso的实现和使用

sso oauth2 的使用

接口获取方式

1、 页面输入如下地址:
http://localhost:8000/oauth/authorize?response_type=code&client_id=client_id_1&redirect_uri=http://localhost:8001/code&scope=write
2、 拦截跳转到登陆页面:
http://localhost:8000/login(当然你也可以通过oauth密码方式获取access_token,将access_token作为上一步中授权接口消息头)
3、 登陆成功后会获取如下内容:
http://localhost:8001/code?code=2tBHA3
4、通过授权码获取token:
http://localhost:8000/oauth/token?grant_type=authorization_code&client_id=client_id_1&client_secret=123456&redirect_uri=http://localhost:8001/code&code=2tBHA3
5、结果如下:
{
  access_token: "ae7e6bbd-0603-4e22-b9be-546c9a673025",
  token_type: "bearer",
  refresh_token: "fb882868-68c7-4532-ba79-4bc368b1b6f0",
  expires_in: 3599,
  scope: "write"
 }

页面跳转方式

1、 页面输入如下地址:
http://localhost:8001/index  ==》 login
2、拦截跳转到登陆页面:
http://localhost:8000/login
3、 登陆成功后会跳转到:
http://localhost:8001/securedPage

Jwt增强版

客户端从认证服务中获取令牌,然后通过令牌访问资源服务。认证服务和资源服务作为独立服务的情况下,资源服务从消息头中拿到令牌是需要通过check_token接口(RemoteTokenServices,具体实现在此类中)访问认证服务,验证令牌的。这里就会有个问题,如果资源服务请求过于频繁、又或者资源服务很多,认证服务资源有限、网络请求效率损耗,势必影响服务性能,所以Jwt解决这个痛点,通过Jwt,我们把常用信息(用户信息)加密写入令牌中,令牌在网络中传递,到达资源服务,只需要通过相同的规则解密令牌就能拿到常用信息,而不需要在请求认证服务的接口在获取了。

关键代码片段

@Order(0)
@Configuration
public class JwtTokenConfig {

    private static final String SIGN_KEY = "qazxsw";

    @Bean
    public TokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    private JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(SIGN_KEY);  // 签名密钥
        jwtAccessTokenConverter.setVerifier(new MacSigner(SIGN_KEY));  // 验证时使用的密钥,和签名密钥保持一致

        DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter() {
            @Override
            public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
                // 获取到request对象
                HttpServletRequest request = ((ServletRequestAttributes) (Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))).getRequest();
                // 获取客户端ip(注意:如果是经过代理之后到达当前服务的话,那么这种方式获取的并不是真实的浏览器客户端ip)
                String remoteAddr = request.getRemoteAddr();
                Map<String, String> stringMap = (Map<String, String>) super.convertAccessToken(token, authentication);
                stringMap.put("clientIp", remoteAddr);
                return stringMap;
            }
        };

        jwtAccessTokenConverter.setAccessTokenConverter(tokenConverter);
        return jwtAccessTokenConverter;
    }

    @Bean
    @Primary
    public DefaultTokenServices defaultTokenServices() {
        // 使用默认实现
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setSupportRefreshToken(true); // 是否开启令牌刷新
        defaultTokenServices.setTokenStore(jwtTokenStore());
        // 针对jwt令牌的添加
        defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
        // 设置令牌有效时间(一般设置为2个小时)
        defaultTokenServices.setAccessTokenValiditySeconds(7200); // access_token就是我们请求资源需要携带的令牌
        // 设置刷新令牌的有效时间
        defaultTokenServices.setRefreshTokenValiditySeconds(259200); // 3天
        return defaultTokenServices;
    }

}

ResourceServerConfig 需要改变为我们定义好的 tokenServices 和 tokenStore

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).tokenServices(defaultTokenServices).tokenStore(tokenStore).stateless(true);
    }

AuthorizationServerConfig 需要改变为我们定义好的 tokenServices 和 tokenStore

 @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.userDetailsService(detailsService)
                .tokenStore(tokenStore)
                .tokenServices(defaultTokenServices)
                .authenticationManager(authenticationManager)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
    }

其他

遇到的问题

1、Possible CSRF detected - state parameter was required but no state could be found

方案解决

server.servlet.session.cookie.name=OAUTH2SESSION

https://blog.csdn.net/JasonYang8088/article/details/80896486

关于权限拦截的使用

  关于ResourceServerConfigurerAdapter和WebSecurityConfigurerAdapter的configure(HttpSecurity http)方法使用,ResourceServerConfigurerAdapter比WebSecurityConfigurerAdapter的优先级要高(鉴于ResourceServerConfiguration的order=3,WebSecurityConfigurerAdapter的order=100)
所以如果是针对状态的请求(需要配置token消息头)过滤优先配置在ResourceServerConfigurerAdapter里面,而后才是针对有状态的请求需要在WebSecurityConfigurerAdapter配置

如下是针对/index请求配置permitAll的日志打印

2019-12-04 10:59:19.907  INFO 8680 --- [nio-8001-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-12-04 10:59:19.907  INFO 8680 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-12-04 10:59:19.915  INFO 8680 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
2019-12-04 10:59:19.946 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/user/**']
2019-12-04 10:59:19.946 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/user/**'
2019-12-04 10:59:19.946 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
2019-12-04 10:59:19.946 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request '/index' matched by universal pattern '/**'
2019-12-04 10:59:19.947 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2019-12-04 10:59:19.948 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2019-12-04 10:59:19.948 DEBUG 8680 --- [nio-8001-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2019-12-04 10:59:19.948 DEBUG 8680 --- [nio-8001-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2019-12-04 10:59:19.950 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 4 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/logout'
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'POST /logout'
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'PUT /logout'
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
2019-12-04 10:59:19.951 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'DELETE /logout'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 5 of 14 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/login'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 6 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'POST /login'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 8 of 14 in additional filter chain; firing Filter: 'DefaultLogoutPageGeneratingFilter'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/logout'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 9 of 14 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.s.HttpSessionRequestCache        : saved request doesn't match
2019-12-04 10:59:19.952 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 10 of 14 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2019-12-04 10:59:19.953 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 11 of 14 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2019-12-04 10:59:19.955 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@cf8cb311: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2019-12-04 10:59:19.955 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 12 of 14 in additional filter chain; firing Filter: 'SessionManagementFilter'
2019-12-04 10:59:19.955 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 13 of 14 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2019-12-04 10:59:19.955 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index at position 14 of 14 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/logout'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'POST /logout'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'PUT /logout'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /index' doesn't match 'DELETE /logout'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/index'; against '/index'
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /index; Attributes: [permitAll]
2019-12-04 10:59:19.956 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@cf8cb311: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2019-12-04 10:59:19.962 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@4b9b85a4, returned: 1
2019-12-04 10:59:19.962 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
2019-12-04 10:59:19.962 DEBUG 8680 --- [nio-8001-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
2019-12-04 10:59:19.963 DEBUG 8680 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /index reached end of additional filter chain; proceeding with original chain

我们会发现如下依次过滤器链

WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
OAuth2ClientAuthenticationProcessingFilter(配置在ResourceServerConfiguration需要拦截的请求)
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor

实现代码

https://github.com/mozovw/delicacy-durian/tree/master/durian-oauth-sso

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure! 我可以帮你解答关于SpringBoot整合oauth2实现token认证的问题。 首先,你需要在你的SpringBoot项目中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 接下来,你需要在你的application.properties文件中进行一些配置,包括oauth2的客户端信息和授权服务器信息。例如: ```properties spring.security.oauth2.client.registration.my-client-id.client-id=your-client-id spring.security.oauth2.client.registration.my-client-id.client-secret=your-client-secret spring.security.oauth2.client.registration.my-client-id.redirect-uri=http://localhost:8080/login/oauth2/code/my-client-id spring.security.oauth2.client.provider.my-client-id.authorization-uri=https://oauth2-provider.com/oauth2/authorize spring.security.oauth2.client.provider.my-client-id.token-uri=https://oauth2-provider.com/oauth2/token spring.security.oauth2.client.provider.my-client-id.user-info-uri=https://oauth2-provider.com/oauth2/userinfo spring.security.oauth2.client.provider.my-client-id.user-name-attribute=name ``` 请替换以上配置中的"your-client-id"、"your-client-secret"、"http://localhost:8080/login/oauth2/code/my-client-id"、"https://oauth2-provider.com/oauth2/authorize"、"https://oauth2-provider.com/oauth2/token"和"https://oauth2-provider.com/oauth2/userinfo"为你实际使用的值。 接下来,你可以创建一个Controller来处理登录和回调的请求。例如: ```java @RestController public class OAuth2Controller { @GetMapping("/login") public RedirectView login() { return new RedirectView("/oauth2/authorization/my-client-id"); } @GetMapping("/login/oauth2/code/my-client-id") public String callback() { return "callback"; } } ``` 在以上示例中,"/login"端点用于触发登录流程,"/login/oauth2/code/my-client-id"端点用于处理认证服务器的回调。 最后,你可以在需要进行token认证的地方使用`@EnableOAuth2Sso`注解来保护你的资源。例如: ```java @Configuration @EnableOAuth2Sso public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/secured-resource").authenticated() .anyRequest().permitAll(); } } ``` 在以上示例中,"/secured-resource"端点需要进行认证,其他端点允许匿名访问。 这就是基于SpringBoot整合oauth2实现token认证的基本步骤。当用户访问受保护的资源时,将会被重定向到认证服务器进行认证,并获得一个有效的访问令牌。 希望以上信息对你有帮助!如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值