Spring Security JWT如何实现SSO单点登录详细解析?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1785个文字,预计阅读时间需要8分钟。
SSO:统一账号在不同系统上登录。使用SpringSecurity实现类似SSO的登录系统十分简单。以下是一个简单DEMO的搭建步骤:
1. 首先来看目录结构: - sso-demo(父工程) - sso-client(客户端项目) - sso-server(服务端项目)
2. 接下来是sso-client项目:
java@Configurationpublic class SsoClientConfig extends WebSecurityConfigurerAdapter { // 配置认证成功处理逻辑 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() // 任何请求都需要认证 .and() .formLogin() // 开启表单登录 .and() .csrf().disable(); // 禁用CSRF保护 }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Bean public UserDetailsService userDetailsService() { return username -> { if (admin.equals(username)) { return new User(username, passwordEncoder().encode(123456), AuthorityUtils.commaSeparatedStringToAuthorityList(admin)); } return null; }; }}
3. 接下来是sso-server项目:
java@Configuration@EnableOAuth2Providerpublic class SsoServerConfig extends WebSecurityConfigurerAdapter { // 配置认证成功处理逻辑 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers(/login).permitAll() // 允许访问登录页面 .anyRequest().authenticated() // 任何请求都需要认证 .and() .formLogin() // 开启表单登录 .and() .csrf().disable(); // 禁用CSRF保护 }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Bean public UserDetailsService userDetailsService() { return username -> { if (admin.equals(username)) { return new User(username, passwordEncoder().encode(123456), AuthorityUtils.commaSeparatedStringToAuthorityList(admin)); } return null; }; }
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }}
4. 在父工程中,配置OAuth2的授权服务器:
java@Configuration@EnableAuthorizationServerpublic class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private UserDetailsService userDetailsService;
@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .userDetailsService(userDetailsService) .tokenStore(jwtTokenStore()); }
@Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security .tokenKeyAccess(permitAll()) // 允许所有客户端访问令牌密钥 .checkTokenAccess(permitAll()) // 允许所有客户端检查令牌 .allowFormAuthenticationForClients(); // 允许客户端表单登录 }
@Bean public JwtTokenStore jwtTokenStore() { return new JwtTokenStore(); }}
5. 最后,在客户端项目中,使用OAuth2进行认证:
javapublic class SsoClient { private RestTemplate restTemplate=new RestTemplate();
public void login(String username, String password) { Map formParams=new HashMap(); formParams.put(username, username); formParams.put(password, password);
ResponseEntity responseEntity=restTemplate.postForEntity(http://localhost:8080/login, formParams, String.class); String accessToken=responseEntity.getBody().split( )[1];
System.out.println(AccessToken: + accessToken); }
public static void main(String[] args) { SsoClient ssoClient=new SsoClient(); ssoClient.login(admin, 123456); }}
运行以上代码,就可以完成一个简单的SSO登录系统。
SSO :同一个帐号在同一个公司不同系统上登陆
使用SpringSecurity实现类似于SSO登陆系统是十分简单的 下面我就搭建一个DEMO
首先来看看目录的结构
其中sso-demo是父工程项目 sso-client 、sso-client2分别对应2个资源服务器,sso-server是认证服务器
引入的pom文件
sso-demo
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>study.security.sso</groupId> <artifactId>sso-demo</artifactId> <version>1.0.0-SNAPSHOT</version> <modules> <module>sso-server</module> <module>sso-client</module> <module>sso-client2</module> </modules> <packaging>pom</packaging> <dependencyManagement> <dependencies> <dependency> <groupId>io.spring.platform</groupId> <artifactId>platform-bom</artifactId> <version>Brussels-SR4</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
sso-server
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>sso-demo</artifactId> <groupId>study.security.sso</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>sso-server</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> </dependencies> </project>
sso-client与sso-client2 pom 中的 是一样的
1.sso-server
现在开始搭建认证服务器
认证服务器的目录结构如下
/** * 认证服务器配置 * Created by ZhuPengWei on 2018/1/11. */ @Configuration @EnableAuthorizationServer public class SsoAuthenticationServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client1") .secret("client1") .authorizedGrantTypes("authorization_code", "refresh_token") .scopes("all") .and() .withClient("client2") .secret("client2") .authorizedGrantTypes("authorization_code", "refresh_token") .scopes("all"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter()); } /** * 认证服务器的安全配置 * * @param security * @throws Exception */ @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // 要访问认证服务器tokenKey的时候需要经过身份认证 security.tokenKeyAccess("isAuthenticated()"); } @Bean public TokenStore jwtTokenStore() { return new JwtTokenStore(jwtAccessTokenConverter()); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); // 保证JWT安全的唯一方式 jwtAccessTokenConverter.setSigningKey("ZPW"); return jwtAccessTokenConverter; } }
/** * 自定义用户登陆逻辑配置 * Created by ZhuPengWei on 2018/1/13. */ @Configuration public class SsoSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; /** * 加密解密逻辑 */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity 127.0.0.1:8060/client2/index.html" rel="external nofollow" >访问client2</a> </body> </html>
application.properties
security.oauth2.client.client-id=client1 security.oauth2.client.client-secret=client1 #需要认证时候跳转的地址 security.oauth2.client.user-authorization-uri=127.0.0.1:9999/server/oauth/authorize #请求令牌地址 security.oauth2.client.access-token-uri=127.0.0.1:9999/server/oauth/token #解析 security.oauth2.resource.jwt.key-uri=127.0.0.1:9999/server/oauth/token_key #sso server.port=8080 server.context-path=/client1
3.sso-client2
资源服务器1和资源服务器2的目录结构是一样的,改了相关的参数
/** * Created by ZhuPengWei on 2018/1/11. */ @SpringBootApplication @RestController @EnableOAuth2Sso public class SsoClient2Application { @GetMapping("/user") public Authentication user(Authentication user) { return user; } public static void main(String[] args) { SpringApplication.run(SsoClient2Application.class, args); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SSO Client2</title> </head> <body> <h1>SSO Demo Client2</h1> <a href="127.0.0.1:8080/client1/index.html" rel="external nofollow" >访问client1</a> </body> </html>
security.oauth2.client.client-id=client2 security.oauth2.client.client-secret=client2 #需要认证时候跳转的地址 security.oauth2.client.user-authorization-uri=127.0.0.1:9999/server/oauth/authorize #请求令牌地址 security.oauth2.client.access-token-uri=127.0.0.1:9999/server/oauth/token #解析 security.oauth2.resource.jwt.key-uri=127.0.0.1:9999/server/oauth/token_key #sso server.port=8060 server.context-path=/client2
好了 基于JWT实现SSO单点登录的DEMO以及搭建完成了 下面来看看页面的效果
在初次访问的时候
图1
登陆成功之后
图2
图3
注意
写SsoApprovalEndPoint与SsoSpelView目的是去掉登陆之后授权的效果如果不写这2个类
在初次访问的登陆成功之后是有一步授权的操作的
比如说图1操作成功之后
点击Authorize才会跳转到图2
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。
本文共计1785个文字,预计阅读时间需要8分钟。
SSO:统一账号在不同系统上登录。使用SpringSecurity实现类似SSO的登录系统十分简单。以下是一个简单DEMO的搭建步骤:
1. 首先来看目录结构: - sso-demo(父工程) - sso-client(客户端项目) - sso-server(服务端项目)
2. 接下来是sso-client项目:
java@Configurationpublic class SsoClientConfig extends WebSecurityConfigurerAdapter { // 配置认证成功处理逻辑 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() // 任何请求都需要认证 .and() .formLogin() // 开启表单登录 .and() .csrf().disable(); // 禁用CSRF保护 }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Bean public UserDetailsService userDetailsService() { return username -> { if (admin.equals(username)) { return new User(username, passwordEncoder().encode(123456), AuthorityUtils.commaSeparatedStringToAuthorityList(admin)); } return null; }; }}
3. 接下来是sso-server项目:
java@Configuration@EnableOAuth2Providerpublic class SsoServerConfig extends WebSecurityConfigurerAdapter { // 配置认证成功处理逻辑 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers(/login).permitAll() // 允许访问登录页面 .anyRequest().authenticated() // 任何请求都需要认证 .and() .formLogin() // 开启表单登录 .and() .csrf().disable(); // 禁用CSRF保护 }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Bean public UserDetailsService userDetailsService() { return username -> { if (admin.equals(username)) { return new User(username, passwordEncoder().encode(123456), AuthorityUtils.commaSeparatedStringToAuthorityList(admin)); } return null; }; }
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }}
4. 在父工程中,配置OAuth2的授权服务器:
java@Configuration@EnableAuthorizationServerpublic class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private UserDetailsService userDetailsService;
@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .userDetailsService(userDetailsService) .tokenStore(jwtTokenStore()); }
@Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security .tokenKeyAccess(permitAll()) // 允许所有客户端访问令牌密钥 .checkTokenAccess(permitAll()) // 允许所有客户端检查令牌 .allowFormAuthenticationForClients(); // 允许客户端表单登录 }
@Bean public JwtTokenStore jwtTokenStore() { return new JwtTokenStore(); }}
5. 最后,在客户端项目中,使用OAuth2进行认证:
javapublic class SsoClient { private RestTemplate restTemplate=new RestTemplate();
public void login(String username, String password) { Map formParams=new HashMap(); formParams.put(username, username); formParams.put(password, password);
ResponseEntity responseEntity=restTemplate.postForEntity(http://localhost:8080/login, formParams, String.class); String accessToken=responseEntity.getBody().split( )[1];
System.out.println(AccessToken: + accessToken); }
public static void main(String[] args) { SsoClient ssoClient=new SsoClient(); ssoClient.login(admin, 123456); }}
运行以上代码,就可以完成一个简单的SSO登录系统。
SSO :同一个帐号在同一个公司不同系统上登陆
使用SpringSecurity实现类似于SSO登陆系统是十分简单的 下面我就搭建一个DEMO
首先来看看目录的结构
其中sso-demo是父工程项目 sso-client 、sso-client2分别对应2个资源服务器,sso-server是认证服务器
引入的pom文件
sso-demo
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>study.security.sso</groupId> <artifactId>sso-demo</artifactId> <version>1.0.0-SNAPSHOT</version> <modules> <module>sso-server</module> <module>sso-client</module> <module>sso-client2</module> </modules> <packaging>pom</packaging> <dependencyManagement> <dependencies> <dependency> <groupId>io.spring.platform</groupId> <artifactId>platform-bom</artifactId> <version>Brussels-SR4</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
sso-server
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>sso-demo</artifactId> <groupId>study.security.sso</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>sso-server</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> </dependencies> </project>
sso-client与sso-client2 pom 中的 是一样的
1.sso-server
现在开始搭建认证服务器
认证服务器的目录结构如下
/** * 认证服务器配置 * Created by ZhuPengWei on 2018/1/11. */ @Configuration @EnableAuthorizationServer public class SsoAuthenticationServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client1") .secret("client1") .authorizedGrantTypes("authorization_code", "refresh_token") .scopes("all") .and() .withClient("client2") .secret("client2") .authorizedGrantTypes("authorization_code", "refresh_token") .scopes("all"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter()); } /** * 认证服务器的安全配置 * * @param security * @throws Exception */ @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // 要访问认证服务器tokenKey的时候需要经过身份认证 security.tokenKeyAccess("isAuthenticated()"); } @Bean public TokenStore jwtTokenStore() { return new JwtTokenStore(jwtAccessTokenConverter()); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); // 保证JWT安全的唯一方式 jwtAccessTokenConverter.setSigningKey("ZPW"); return jwtAccessTokenConverter; } }
/** * 自定义用户登陆逻辑配置 * Created by ZhuPengWei on 2018/1/13. */ @Configuration public class SsoSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; /** * 加密解密逻辑 */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity 127.0.0.1:8060/client2/index.html" rel="external nofollow" >访问client2</a> </body> </html>
application.properties
security.oauth2.client.client-id=client1 security.oauth2.client.client-secret=client1 #需要认证时候跳转的地址 security.oauth2.client.user-authorization-uri=127.0.0.1:9999/server/oauth/authorize #请求令牌地址 security.oauth2.client.access-token-uri=127.0.0.1:9999/server/oauth/token #解析 security.oauth2.resource.jwt.key-uri=127.0.0.1:9999/server/oauth/token_key #sso server.port=8080 server.context-path=/client1
3.sso-client2
资源服务器1和资源服务器2的目录结构是一样的,改了相关的参数
/** * Created by ZhuPengWei on 2018/1/11. */ @SpringBootApplication @RestController @EnableOAuth2Sso public class SsoClient2Application { @GetMapping("/user") public Authentication user(Authentication user) { return user; } public static void main(String[] args) { SpringApplication.run(SsoClient2Application.class, args); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SSO Client2</title> </head> <body> <h1>SSO Demo Client2</h1> <a href="127.0.0.1:8080/client1/index.html" rel="external nofollow" >访问client1</a> </body> </html>
security.oauth2.client.client-id=client2 security.oauth2.client.client-secret=client2 #需要认证时候跳转的地址 security.oauth2.client.user-authorization-uri=127.0.0.1:9999/server/oauth/authorize #请求令牌地址 security.oauth2.client.access-token-uri=127.0.0.1:9999/server/oauth/token #解析 security.oauth2.resource.jwt.key-uri=127.0.0.1:9999/server/oauth/token_key #sso server.port=8060 server.context-path=/client2
好了 基于JWT实现SSO单点登录的DEMO以及搭建完成了 下面来看看页面的效果
在初次访问的时候
图1
登陆成功之后
图2
图3
注意
写SsoApprovalEndPoint与SsoSpelView目的是去掉登陆之后授权的效果如果不写这2个类
在初次访问的登陆成功之后是有一步授权的操作的
比如说图1操作成功之后
点击Authorize才会跳转到图2
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

