三. 单点登录示例

一 . 概述

单点登录(Singal Sign On)是很多企业经常使用的一种登录方式,那么何为单点登录呢?为了解决什么样的问题呢?举个例子,在淘宝公司内部,有天猫、淘宝、阿里云、聚划算等众多的产品线,这些产品线是不同的服务器来支撑运行,但是作为用户的我们却可以使用同一套账户名和密码进行登录他几乎所有的产品,登录服务器只有一个,根据登录服务器返回的特定的信息,可以去访问它所有的产品线。着就是所谓的单点登录。

1.1 认证服务器

  • 三. 单点登录示例_第1张图片

依赖


    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.security.oauth
        spring-security-oauth2
        2.3.6.RELEASE
    
    
        org.springframework.security.oauth.boot
        spring-security-oauth2-autoconfigure
        2.1.9.RELEASE
    
    
        org.slf4j
        slf4j-api
    

Yml配置

server:
  port: 7070

  servlet:
    context-path: /auth

授权服务

@EnableAuthorizationServer
@Configuration
public class JwtServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    // jwt的生成器
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("abcxyz");
        return jwtAccessTokenConverter;
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.accessTokenConverter(jwtAccessTokenConverter())  //配置JWT的生成器
                 .allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET);
    }
    // 客户端的配置
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()  //
                .withClient("client-a") // client_id
                .secret("$2a$10$GqJuJhe7zmtwwThIed7smu9zMJBgSQzFMP47eEDL.g9tg8Y82.A7m") // client_secret
                .authorizedGrantTypes("authorization_code")  //采用什么方式获取access_token
                .redirectUris("http://localhost:8081/clientA/login")
                .scopes("all")
                .autoApprove(true) //自动授权
                .and()
                .withClient("client-b") // client_id
                .secret("$2a$10$GqJuJhe7zmtwwThIed7smu9zMJBgSQzFMP47eEDL.g9tg8Y82.A7m") // client_secret
                .authorizedGrantTypes("authorization_code")  //采用什么方式获取access_token
                .redirectUris("http://localhost:8082/clientB/login")
                .scopes("all")
                .autoApprove(true);
    }
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .checkTokenAccess("isAuthenticated()")
                .passwordEncoder(passwordEncoder);
    }
}

安全配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 该bean的作用是,在UserDetailsService接口的loadUserByUsername返回的UserDetail中包含了
     * password, 该bean就将用户从页面提交过来的密码进行处理,处理之后与UserDetail中密码进行比较。
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    // 统一安全配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 意思是将图片验证码过滤器,加载用户名密码验证过滤器之前
        http.formLogin()  //使用form进行登录
                .loginPage("/login.html")   //指定登录页面
                .loginProcessingUrl("/authentication/form")  //表示form往哪里进行提交
                .and()
                .authorizeRequests()
                .antMatchers("/login.html", "/images/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }
    // 密码加密处理
    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        System.out.println(bCryptPasswordEncoder.encode("1"));
    }
}

自定义认证

// 该类的作用是处理用户登录名和密码
@Component
public class UserSecurityService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = new User(username,
                "$2a$10$GqJuJhe7zmtwwThIed7smu9zMJBgSQzFMP47eEDL.g9tg8Y82.A7m",
                Arrays.asList(new SimpleGrantedAuthority("ROLE_user"), new SimpleGrantedAuthority("ROLE_admin")));
        return user;
    }
}

登录页面


    

用户登录

username:
Password:

1.2 子系统client-a

  • 三. 单点登录示例_第2张图片

依赖


    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.security.oauth
        spring-security-oauth2
        2.3.6.RELEASE
    
    
        org.springframework.boot
        spring-boot-starter-security
    
    
        org.springframework.security.oauth.boot
        spring-security-oauth2-autoconfigure
        2.1.9.RELEASE
    

配置

server:
  port: 8081
  servlet:
    context-path: /clientA

security:
  oauth2:
    client:
      client-id: client-a
      client-secret: 1
      # 在每个服务器中要保存 access_token
      access-token-uri: http://localhost:7070/auth/oauth/token
      user-authorization-uri: http://localhost:7070/auth/oauth/authorize

    resource:
      jwt:
        key-value: abcxyz  #验签

启动类配置

@SpringBootApplication
@EnableOAuth2Sso
// 启动权限认证
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled=true)
public class SsoClientApplicationA {
    public static void main(String[] args) {
        SpringApplication.run(SsoClientApplicationA.class, args);
    }
}

controller示例

@RequestMapping
@RestController
public class UserController {
    @RequestMapping("/user")
    @PreAuthorize("hasAuthority('ROLE_admin')")
    public Object get(Authentication authentication) {
        System.out.println("ClientA: " + authentication.getName() + ";;" + authentication.getAuthorities());
        return "clientA";
    }
    @RequestMapping("/login")
    @PreAuthorize("hasAuthority('ROLE_admin')")
    public Object hello(Authentication authentication) {
        System.out.println("ClientA: " + authentication.getName() + ";;" + authentication.getAuthorities());
        return "hello_A";
    }
}

index.html




    
    Title


    

应用AAAA

访问B服务

1.2 子系统client-b

  • 三. 单点登录示例_第3张图片

依赖

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-security
        
        
            org.springframework.security.oauth
            spring-security-oauth2
            2.3.6.RELEASE
        
        
            org.springframework.security.oauth.boot
            spring-security-oauth2-autoconfigure
            2.1.9.RELEASE
        

yml配置

server:
  port: 8082
  servlet:
    context-path: /clientB

security:
  oauth2:
    client:
      client-id: client-b
      client-secret: 1
      access-token-uri: http://localhost:7070/auth/oauth/token
      user-authorization-uri: http://localhost:7070/auth/oauth/authorize

    resource:
      jwt:
        key-value: abcxyz  #验签

启动类配置

@SpringBootApplication
@EnableOAuth2Sso
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled=true)
public class SsoClientApplicationB {
    public static void main(String[] args) {
        SpringApplication.run(SsoClientApplicationB.class, args);
    }
}

controller示例

@RestController
@RequestMapping
public class UserController {

    @RequestMapping("/info")
    @RolesAllowed("ROLE_admin")
    public Object get(Authentication authentication) {
        System.out.println("ClientB: " + authentication.getName() + ";;" + authentication.getAuthorities());
        return "clientA";
    }
    @RequestMapping
    @RolesAllowed("ROLE_admin")
    public Object hello(Authentication authentication) {
        System.out.println("ClientB: " + authentication.getName() + ";;" + authentication.getAuthorities());
        return "hello_B";
    }
}

index.html




    
    Title


    

应用B

访问A服务

源码: 链接:https://pan.baidu.com/s/1hDeo-gMwuStKaL1mniUDog&shfl=sharepset 密码:t4s4

你可能感兴趣的:(三. 单点登录示例)