美文网首页Spring Security
Spring Security源码分析十二:Spring Sec

Spring Security源码分析十二:Spring Sec

作者: 淡淡的伤你 | 来源:发表于2018-01-25 23:33 被阅读243次

    单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指,只需要单一的注销动作,就可以结束对于多个系统的访问权限。

    Security OAuth2 单点登录流程示意图

    https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/SpringSecurity-OAuth2-sso.png
    1. 访问client1
    2. client1将请求导向sso-server
    3. 同意授权
    4. 携带授权码code返回client1
    5. client1拿着授权码请求令牌
    6. 返回JWT令牌
    7. client1解析令牌并登录
    8. client1访问client2
    9. client2将请求导向sso-server
    10. 同意授权
    11. 携带授权码code返回client2
    12. client2拿着授权码请求令牌
    13. 返回JWT令牌
    14. client2解析令牌并登录

    用户的登录状态是由sso-server认证中心来保存的,登录界面和账号密码的验证也是sso-server认证中心来做的(client1clien2返回token是不同的,但解析出来的用户信息是同一个用户)。

    Security OAuth2 实现单点登录

    项目结构

    https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth2-sso01.png

    sso-server

    认证服务器

    @Configuration
    @EnableAuthorizationServer
    public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
        /**
         * 客户端一些配置
         * @param clients
         * @throws Exception
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("merryyou1")
                    .secret("merryyousecrect1")
                    .authorizedGrantTypes("authorization_code", "refresh_token")
                    .scopes("all")
                    .and()
                    .withClient("merryyou2")
                    .secret("merryyousecrect2")
                    .authorizedGrantTypes("authorization_code", "refresh_token")
                    .scopes("all");
        }
    
        /**
         * 配置jwttokenStore
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter());
        }
    
        /**
         * springSecurity 授权表达式,访问merryyou tokenkey时需要经过认证
         * @param security
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.tokenKeyAccess("isAuthenticated()");
        }
    
        /**
         * JWTtokenStore
         * @return
         */
        @Bean
        public TokenStore jwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    
        /**
         * 生成JTW token
         * @return
         */
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey("merryyou");
            return converter;
        }
    }
    

    security配置

    @Configuration
    public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin().loginPage("/authentication/require")
                    .loginProcessingUrl("/authentication/form")
                    .and().authorizeRequests()
                    .antMatchers("/authentication/require",
                            "/authentication/form",
                            "/**/*.js",
                            "/**/*.css",
                            "/**/*.jpg",
                            "/**/*.png",
                            "/**/*.woff2"
                    )
                    .permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .csrf().disable();
    //        http.formLogin().and().authorizeRequests().anyRequest().authenticated();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }
    }
    

    SsoUserDetailsService

    @Component
    public class SsoUserDetailsService implements UserDetailsService {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            return new User(username, passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
        }
    }
    

    application.yml

    server:
      port: 8082
      context-path: /uaa
    spring:
      freemarker:
        allow-request-override: false
        allow-session-override: false
        cache: true
        charset: UTF-8
        check-template-location: true
        content-type: text/html
        enabled: true
        expose-request-attributes: false
        expose-session-attributes: false
        expose-spring-macro-helpers: true
        prefer-file-system-access: true
        suffix: .ftl
        template-loader-path: classpath:/templates/
    

    sso-client1

    SsoClient1Application

    @SpringBootApplication
    @RestController
    @EnableOAuth2Sso
    public class SsoClient1Application {
    
        @GetMapping("/user")
        public Authentication user(Authentication user) {
            return user;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(SsoClient1Application.class, args);
        }
    }
    

    application.yml

    auth-server: http://localhost:8082/uaa # sso-server地址
    server:
      context-path: /client1
      port: 8083
    security:
      oauth2:
        client:
          client-id: merryyou1
          client-secret: merryyousecrect1
          user-authorization-uri: ${auth-server}/oauth/authorize #请求认证的地址
          access-token-uri: ${auth-server}/oauth/token #请求令牌的地址
        resource:
          jwt:
            key-uri: ${auth-server}/oauth/token_key #解析jwt令牌所需要密钥的地址
    

    sso-client2

    同sso-client1一致

    效果如下:
    [图片上传失败...(image-1c6041-1516894354927)]

    代码下载

    从我的 github 中下载,https://github.com/longfeizheng/sso-merryyou

    相关文章

      网友评论

        本文标题:Spring Security源码分析十二:Spring Sec

        本文链接:https://www.haomeiwen.com/subject/sbobaxtx.html