基于Spring Security OAuth2.0实现单点登录SSO

1.概述

本文简要总结一下如果使用Spring Security OAuth和Spring Boot来实现SSO,文末有样例代码。不了解OAuth2.0协议的同学请参考“OAuth2.0协议原理详解”
整个工程包括三个独立的应用,一个认证服务和两个客户端应用,结构非常简单。当一个用户访问客户端应用中被防护的API时,系统会被自动重定向到认证服务,之后我们使用OAuth2.0的授权码授权方式来实现认证授权。

2.客户端APP

我们先从客户端应用入手,使用Spring Boot可以最大程度简化配置

2.1 Maven依赖

	<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>

2.2安全配置

客户端的安全配置如下:
	@Configuration
	@EnableOAuth2Sso
	public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
	 @Override
	  public void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/**")
      .authorizeRequests()
      .antMatchers("/", "/login**")
      .permitAll()
      .anyRequest()
      .authenticated();
  }
}

配置最核心的部分是@ EnableOAuth2Sso注解来开启SSO。这里要注意,我们需要重写WebSecurityConfigurerAdapter否则所有的路径都会受到SSO的保护,这样无论用户访问哪个页面都会被重定向到登录页面,在这个例子里,指数和登录页面是唯一不需要被防护的。
最后,我们定义一个RequestContextListener bean来处理请求范围。

	application.yml:
	server:
 		   port: 8082
	  	 context-path: /ui
			session:
      		cookie:
   		 name: UISESSION
	security:
		basic:
			 enabled: false
	 		 oauth2:
    		client:
  			clientId: SampleClientId
  			clientSecret: secret
  			accessTokenUri: http://localhost:8081/auth/oauth/token
 		 userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    		resource:
	  userInfoUri: http://localhost:8081/auth/user/me
spring:
	  thymeleaf:
		cache: false

说明:

我们禁用了默认的基本身份验证
accessTokenUri是获取访问令牌的URL
userAuthorizationUri是授权用户被重定向的目标URL
userInfoUri是用户终端访问用户信息的URL

在这个案里,认证服务是我们自己建设的,但是在实际的应用场景下认证服务往往是第三方提供的比如Facebook或者gitHub
2.3前端
前端并非本文的重点,这里简单提一下客户端有一个非常简单的前端页面。

index.html的:

	<h1>Spring Security SSO</h1>

	<a href="securedPage">Login</a>

		securedPage.html:
	<h1>Secured   Page</h1>

	Welcome, <span th:text="${#authentication.name}">Name</span>

securedPage.html需要用户通过授权才能访问,如果一个未授权的用户访问这个页面,他会被重定向到登录页面

3.认证服务器

3.1 Maven依赖

	<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>

3.2 OAuth配置

本例中我们把AS(认证服务)器和RS放(资源服务器)在一个实例中部署。
RS配置如下:

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

AS配置如下:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("permitAll()")
      .checkTokenAccess("isAuthenticated()");
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
      .withClient("SampleClientId")
      .secret("secret")
      .authorizedGrantTypes("authorization_code")
      .scopes("user_info")
      .autoApprove(true) ; 
}

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

}

这里我们只开启authorization_code授权模式,另外这里注意到自动审批=真,这意味着用户不会被重定向到授权的页面,也不需要手动给请求授权。

3.3安全配置

这里需要定义一个简单的认证机制
@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 {
    auth.parentAuthenticationManager(authenticationManager)
      .inMemoryAuthentication()
      .withUser("john").password("123").roles("USER");
}

}

注意,我们用了内存认证,这里只是做一个简单的例子,我们直接把账号密码写到内存里了,真正使用的时候这里要换成自定义的UserDetailsS​​ervice的。

3.4用户终端

一个很简单的返回JSON消息的接口
@RestController

public class UserController {

@GetMapping("/user/me")

public Principal user(Principal principal) {
    return principal;
}

}

完整的代码下载链接:Over On Github
参考资料:
http://blog.csdn.net/j754379117/article/details/70175198
http://www.baeldung.com/sso-spring-security-oauth2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值