Spring Security OAuth2 实现SSO

SSO即Single Sign-On,单点登录,即授权服务器形式,通过在一个网站上登录完后,给予过授权的就可以直接用这个帐号信息登录了,类似于qq微信登录其他APP。
本篇文章,将利用Spring Security实现简单的单点登录中需要的,认证服务器和客户端。

原文链接:http://www.baeldung.com/sso-spring-security-oauth2

SSO服务器

首先实现一个SSO服务器,下面是基本的pom文件:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>

启动main方法:
这里面主要用EnableResourceServer来开启资源服务器。

@SpringBootApplication
@EnableResourceServer
public class SsoServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SsoServerApplication.class, args);
    }
}

下面再分别介绍Spring Security和OAuth2的Config类:
以下是OAuth2的Config类:

//Auth2的配置文件
@Configuration
@EnableAuthorizationServer
public class Auth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;    //使用默认的认证管家

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")         //能够获取token的
                .checkTokenAccess("isAuthenticated()");     //检测是否认证
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("SampleClientId")     //接受的clientId
                .secret("secret")                         //默认secret
                .authorizedGrantTypes("authorization_code")  //授权模式
                .scopes("user_info")                       //范围,只获取用户认证。
                .autoApprove(true);
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

Auth2Config 定义了一些Auth2的信息,例如对名为SampleClientId的注册,以及对认证规则的定义:

oauthServer.tokenKeyAccess("permitAll()")         //能够获取token的
                .checkTokenAccess("isAuthenticated()");     //检测是否认证

以下是Spring Security的配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    protected void configure(HttpSecurity http) throws Exception { 
        http.requestMatchers()
                .antMatchers("/login", "/oauth/authorize")
                .and()
                .authorizeRequests()    //请求授权,后面的需要授权。
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()             //登录表单开放给所有人,默认的登录表单。
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off
        auth.parentAuthenticationManager(authenticationManager)
                .inMemoryAuthentication()
                .withUser("anla7856")     //模拟一个注册用户名
                .password("123456")
                .roles("USER");
    }
}

下面是application.yml配置:

server:
  port: 8080
  context-path: /auth
security:
  basic:
    enabled: false          #阻止基本认证

下面是sso客户端代码:

SSO客户端

sso客户端,也是基于Spring Security实现,下面是其pom文件:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>

再看看启动Application类:

扫描二维码关注公众号,回复: 3285096 查看本文章
@SpringBootApplication
public class SsoClientApplication {
    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }                 //自定义一个RequestContextListener

    public static void main(String[] args) {
        SpringApplication.run(SsoClientApplication.class, args);
    }
}

接下来是Spring Security的配置文件:

@EnableOAuth2Sso
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }
}

下面是 WebMvcConfig:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Override
    public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
        configurer.enable();      //使配置生效
    }

    /**
     * 配置view
     * @param registry
     */
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
        super.addViewControllers(registry);
        registry.addViewController("/")
                .setViewName("forward:/index");
        registry.addViewController("/index");
        registry.addViewController("/securedPage");
    }

    /**
     * 映射资源文件
     * @param registry
     */
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/");
    }
}

application.yml文件:

server:
    port: 8989
    session:
      cookie:
        name: UI2SESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId      #与server端对应
      clientSecret: secret          #与服务端对应
      accessTokenUri: http://localhost:8080/auth/oauth/token
      userAuthorizationUri: http://localhost:8080/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8080/auth/door/me     #资源服务器,即对sso server的资源访问。
spring:
  thymeleaf:
    cache: false

整体的架构也算搭好了,server端和client端都是用Spring Security,当用户访问client的页面时,由Spring Security控制,会使其跳转到sso Server端的默认login页面进行验证,也就是在Server端配置好的clientid,当验证用户名密码通过时,返回给给客户端,此时客户端从security.oauth2.resource.userInfoUri的资源服务器下获取相应的资源。

代码在hello-springcloud 下的v6分支。

参考资料:
1. http://www.baeldung.com/sso-spring-security-oauth2
2. https://projects.spring.io/spring-security-oauth/docs/oauth2.html
3. https://spring.io/projects/spring-security
4. http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
5. https://blog.csdn.net/xiejx618/article/details/51039653

猜你喜欢

转载自blog.csdn.net/anLA_/article/details/80779640