当前位置:   article > 正文

SpringBoot+OAuth2+JWT实现单点登录SSO完整教程,竟如此简单优雅!

springboot oauth2.0单点登录

作者:狂乱的贵公子

来源:https://www.cnblogs.com/cjsblog/p/10548022.html

1.前言

技术这东西吧,看别人写的好像很简单似的,到自己去写的时候就各种问题,“一看就会,一做就错”。网上关于实现SSO的文章一大堆,但是当你真的照着写的时候就会发现根本不是那么回事儿,简直让人抓狂,尤其是对于我这样的菜鸟。几经曲折,终于搞定了,决定记录下来,以便后续查看。先来看一下效果

2.准备

2.1. 单点登录

最常见的例子是,我们打开淘宝APP,首页就会有天猫、聚划算等服务的链接,当你点击以后就直接跳过去了,并没有让你再登录一次

下面这个图是我再网上找的,我觉得画得比较明白:

可惜有点儿不清晰,于是我又画了个简版的:

重要的是理解:

  • SSO服务端和SSO客户端直接是通过授权以后发放Token的形式来访问受保护的资源

  • 相对于浏览器来说,业务系统是服务端,相对于SSO服务端来说,业务系统是客户端

  • 浏览器和业务系统之间通过会话正常访问

  • 不是每次浏览器请求都要去SSO服务端去验证,只要浏览器和它所访问的服务端的会话有效它就可以正常访问

2.2. OAuth2

推荐以下几篇博客

《OAuth 2.0》

《Spring Security对OAuth2的支持》

3.利用OAuth2实现单点登录

接下来,只讲跟本例相关的一些配置,不讲原理,不讲为什么

众所周知,在OAuth2在有授权服务器、资源服务器、客户端这样几个角色,当我们用它来实现SSO的时候是不需要资源服务器这个角色的,有授权服务器和客户端就够了。

授权服务器当然是用来做认证的,客户端就是各个应用系统,我们只需要登录成功后拿到用户信息以及用户所拥有的权限即可

之前我一直认为把那些需要权限控制的资源放到资源服务器里保护起来就可以实现权限控制,其实是我想错了,权限控制还得通过Spring Security或者自定义拦截器来做

3.1. Spring Security 、OAuth2、JWT、SSO

在本例中,一定要分清楚这几个的作用

首先,SSO是一种思想,或者说是一种解决方案,是抽象的,我们要做的就是按照它的这种思想去实现它

其次,OAuth2是用来允许用户授权第三方应用访问他在另一个服务器上的资源的一种协议,它不是用来做单点登录的,但我们可以利用它来实现单点登录。在本例实现SSO的过程中,受保护的资源就是用户的信息(包括,用户的基本信息,以及用户所具有的权限),而我们想要访问这这一资源就需要用户登录并授权,OAuth2服务端负责令牌的发放等操作,这令牌的生成我们采用JWT,也就是说JWT是用来承载用户的Access_Token的

最后,Spring Security是用于安全访问的,这里我们我们用来做访问权限控制

4.认证服务器配置

4.1. Maven依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>org.springframework.boot</groupId>
  7.         <artifactId>spring-boot-starter-parent</artifactId>
  8.         <version>2.1.3.RELEASE</version>
  9.         <relativePath/> <!-- lookup parent from repository -->
  10.     </parent>
  11.     <groupId>com.cjs.sso</groupId>
  12.     <artifactId>oauth2-sso-auth-server</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>oauth2-sso-auth-server</name>
  15.     <properties>
  16.         <java.version>1.8</java.version>
  17.     </properties>
  18.     <dependencies>
  19.         <dependency>
  20.             <groupId>org.springframework.boot</groupId>
  21.             <artifactId>spring-boot-starter-data-jpa</artifactId>
  22.         </dependency>
  23.         <dependency>
  24.             <groupId>org.springframework.boot</groupId>
  25.             <artifactId>spring-boot-starter-data-redis</artifactId>
  26.         </dependency>
  27.         <dependency>
  28.             <groupId>org.springframework.boot</groupId>
  29.             <artifactId>spring-boot-starter-security</artifactId>
  30.         </dependency>
  31.         <dependency>
  32.             <groupId>org.springframework.security.oauth.boot</groupId>
  33.             <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  34.             <version>2.1.3.RELEASE</version>
  35.         </dependency>
  36.         <dependency>
  37.             <groupId>org.springframework.boot</groupId>
  38.             <artifactId>spring-boot-starter-thymeleaf</artifactId>
  39.         </dependency>
  40.         <dependency>
  41.             <groupId>org.springframework.boot</groupId>
  42.             <artifactId>spring-boot-starter-web</artifactId>
  43.         </dependency>
  44.         <dependency>
  45.             <groupId>org.springframework.session</groupId>
  46.             <artifactId>spring-session-data-redis</artifactId>
  47.         </dependency>
  48.         <dependency>
  49.             <groupId>mysql</groupId>
  50.             <artifactId>mysql-connector-java</artifactId>
  51.             <scope>runtime</scope>
  52.         </dependency>
  53.         <dependency>
  54.             <groupId>org.projectlombok</groupId>
  55.             <artifactId>lombok</artifactId>
  56.             <optional>true</optional>
  57.         </dependency>
  58.         <dependency>
  59.             <groupId>org.springframework.boot</groupId>
  60.             <artifactId>spring-boot-starter-test</artifactId>
  61.             <scope>test</scope>
  62.         </dependency>
  63.         <dependency>
  64.             <groupId>org.springframework.security</groupId>
  65.             <artifactId>spring-security-test</artifactId>
  66.             <scope>test</scope>
  67.         </dependency>
  68.         <dependency>
  69.             <groupId>org.apache.commons</groupId>
  70.             <artifactId>commons-lang3</artifactId>
  71.             <version>3.8.1</version>
  72.         </dependency>
  73.         <dependency>
  74.             <groupId>com.alibaba</groupId>
  75.             <artifactId>fastjson</artifactId>
  76.             <version>1.2.56</version>
  77.         </dependency>
  78.     </dependencies>
  79.     <build>
  80.         <plugins>
  81.             <plugin>
  82.                 <groupId>org.springframework.boot</groupId>
  83.                 <artifactId>spring-boot-maven-plugin</artifactId>
  84.             </plugin>
  85.         </plugins>
  86.     </build>
  87. </project>

这里面最重要的依赖是:spring-security-oauth2-autoconfigure

4.2. application.yml

  1. spring:
  2.   datasource:
  3.     url: jdbc:mysql://localhost:3306/permission
  4.     username: root
  5.     password: 123456
  6.     driver-class-name: com.mysql.jdbc.Driver
  7.   jpa:
  8.     show-sql: true
  9.   session:
  10.     store-type: redis
  11.   redis:
  12.     host: 127.0.0.1
  13.     password: 123456
  14.     port: 6379
  15. server:
  16.   port: 8080

4.3. AuthorizationServerConfig(重要)

  1. package com.cjs.sso.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.context.annotation.Primary;
  6. import org.springframework.security.core.token.DefaultToken;
  7. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  8. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  9. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
  10. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
  11. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
  12. import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
  13. import org.springframework.security.oauth2.provider.token.TokenStore;
  14. import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  15. import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  16. import javax.sql.DataSource;
  17. /**
  18.  * @author ChengJianSheng
  19.  * @date 2019-02-11
  20.  */
  21. @Configuration
  22. @EnableAuthorizationServer
  23. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  24.     @Autowired
  25.     private DataSource dataSource;
  26.     @Override
  27.     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  28.         security.allowFormAuthenticationForClients();
  29.         security.tokenKeyAccess("isAuthenticated()");
  30.     }
  31.     @Override
  32.     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  33.         clients.jdbc(dataSource);
  34.     }
  35.     @Override
  36.     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  37.         endpoints.accessTokenConverter(jwtAccessTokenConverter());
  38.         endpoints.tokenStore(jwtTokenStore());
  39. //        endpoints.tokenServices(defaultTokenServices());
  40.     }
  41.     /*@Primary
  42.     @Bean
  43.     public DefaultTokenServices defaultTokenServices() {
  44.         DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
  45.         defaultTokenServices.setTokenStore(jwtTokenStore());
  46.         defaultTokenServices.setSupportRefreshToken(true);
  47.         return defaultTokenServices;
  48.     }*/
  49.     @Bean
  50.     public JwtTokenStore jwtTokenStore() {
  51.         return new JwtTokenStore(jwtAccessTokenConverter());
  52.     }
  53.     @Bean
  54.     public JwtAccessTokenConverter jwtAccessTokenConverter() {
  55.         JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
  56.         jwtAccessTokenConverter.setSigningKey("cjs");   //  Sets the JWT signing key
  57.         return jwtAccessTokenConverter;
  58.     }
  59. }

说明:

  1. 别忘了**@EnableAuthorizationServer**

  2. Token存储采用的是JWT

  3. 客户端以及登录用户这些配置存储在数据库,为了减少数据库的查询次数,可以从数据库读出来以后再放到内存中

4.4. WebSecurityConfig(重要)

  1. package com.cjs.sso.config;
  2. import com.cjs.sso.service.MyUserDetailsService;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  7. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  8. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  9. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  11. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  12. import org.springframework.security.crypto.password.PasswordEncoder;
  13. /**
  14.  * @author ChengJianSheng
  15.  * @date 2019-02-11
  16.  */
  17. @Configuration
  18. @EnableWebSecurity
  19. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  20.     @Autowired
  21.     private MyUserDetailsService userDetailsService;
  22.     @Override
  23.     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  24.         auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
  25.     }
  26.     @Override
  27.     public void configure(WebSecurity web) throws Exception {
  28.         web.ignoring().antMatchers("/assets/**""/css/**""/images/**");
  29.     }
  30.     @Override
  31.     protected void configure(HttpSecurity http) throws Exception {
  32.         http.formLogin()
  33.                 .loginPage("/login")
  34.                 .and()
  35.                 .authorizeRequests()
  36.                 .antMatchers("/login").permitAll()
  37.                 .anyRequest()
  38.                 .authenticated()
  39.                 .and().csrf().disable().cors();
  40.     }
  41.     @Bean
  42.     public PasswordEncoder passwordEncoder() {
  43.         return new BCryptPasswordEncoder();
  44.     }
  45. }

4.5. 自定义登录页面(一般来讲都是要自定义的)

  1. package com.cjs.sso.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. /**
  5.  * @author ChengJianSheng
  6.  * @date 2019-02-12
  7.  */
  8. @Controller
  9. public class LoginController {
  10.     @GetMapping("/login")
  11.     public String login() {
  12.         return "login";
  13.     }
  14.     @GetMapping("/")
  15.     public String index() {
  16.         return "index";
  17.     }
  18. }

自定义登录页面的时候,只需要准备一个登录页面,然后写个Controller令其可以访问到即可,登录页面表单提交的时候method一定要是post,最重要的时候action要跟访问登录页面的url一样

千万记住了,访问登录页面的时候是GET请求,表单提交的时候是POST请求,其它的就不用管了

  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="utf-8">
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6.     <title>Ela Admin - HTML5 Admin Template</title>
  7.     <meta name="description" content="Ela Admin - HTML5 Admin Template">
  8.     <meta name="viewport" content="width=device-width, initial-scale=1">
  9.     <link type="text/css" rel="stylesheet" th:href="@{/assets/css/normalize.css}">
  10.     <link type="text/css" rel="stylesheet" th:href="@{/assets/bootstrap-4.3.1-dist/css/bootstrap.min.css}">
  11.     <link type="text/css" rel="stylesheet" th:href="@{/assets/css/font-awesome.min.css}">
  12.     <link type="text/css" rel="stylesheet" th:href="@{/assets/css/style.css}">
  13. </head>
  14. <body class="bg-dark">
  15. <div class="sufee-login d-flex align-content-center flex-wrap">
  16.     <div class="container">
  17.         <div class="login-content">
  18.             <div class="login-logo">
  19.                 <h1 style="color: #57bf95;">欢迎来到王者荣耀</h1>
  20.             </div>
  21.             <div class="login-form">
  22.                 <form th:action="@{/login}" method="post">
  23.                     <div class="form-group">
  24.                         <label>Username</label>
  25.                         <input type="text" class="form-control" name="username" placeholder="Username">
  26.                     </div>
  27.                     <div class="form-group">
  28.                         <label>Password</label>
  29.                         <input type="password" class="form-control" name="password" placeholder="Password">
  30.                     </div>
  31.                     <div class="checkbox">
  32.                         <label>
  33.                             <input type="checkbox"> Remember Me
  34.                         </label>
  35.                         <label class="pull-right">
  36.                             <a href="#">Forgotten Password?</a>
  37.                         </label>
  38.                     </div>
  39.                     <button type="submit" class="btn btn-success btn-flat m-b-30 m-t-30" style="font-size: 18px;">登录</button>
  40.                 </form>
  41.             </div>
  42.         </div>
  43.     </div>
  44. </div>
  45. <script type="text/javascript" th:src="@{/assets/js/jquery-2.1.4.min.js}"></script>
  46. <script type="text/javascript" th:src="@{/assets/bootstrap-4.3.1-dist/js/bootstrap.min.js}"></script>
  47. <script type="text/javascript" th:src="@{/assets/js/main.js}"></script>
  48. </body>
  49. </html>

4.6. 定义客户端

4.7. 加载用户

登录账户

  1. package com.cjs.sso.domain;
  2. import lombok.Data;
  3. import org.springframework.security.core.GrantedAuthority;
  4. import org.springframework.security.core.userdetails.User;
  5. import java.util.Collection;
  6. /**
  7.  * 大部分时候直接用User即可不必扩展
  8.  * @author ChengJianSheng
  9.  * @date 2019-02-11
  10.  */
  11. @Data
  12. public class MyUser extends User {
  13.     private Integer departmentId;   //  举个例子,部门ID
  14.     private String mobile;  //  举个例子,假设我们想增加一个字段,这里我们增加一个mobile表示手机号
  15.     public MyUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
  16.         super(username, password, authorities);
  17.     }
  18.     public MyUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
  19.         super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
  20.     }
  21. }

加载登录账户

  1. package com.cjs.sso.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.cjs.sso.domain.MyUser;
  4. import com.cjs.sso.entity.SysPermission;
  5. import com.cjs.sso.entity.SysUser;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  9. import org.springframework.security.core.userdetails.UserDetails;
  10. import org.springframework.security.core.userdetails.UserDetailsService;
  11. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  12. import org.springframework.security.crypto.password.PasswordEncoder;
  13. import org.springframework.stereotype.Service;
  14. import org.springframework.util.CollectionUtils;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. /**
  18.  * @author ChengJianSheng
  19.  * @date 2019-02-11
  20.  */
  21. @Slf4j
  22. @Service
  23. public class MyUserDetailsService implements UserDetailsService {
  24.     @Autowired
  25.     private PasswordEncoder passwordEncoder;
  26.     @Autowired
  27.     private UserService userService;
  28.     @Autowired
  29.     private PermissionService permissionService;
  30.     @Override
  31.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  32.         SysUser sysUser = userService.getByUsername(username);
  33.         if (null == sysUser) {
  34.             log.warn("用户{}不存在", username);
  35.             throw new UsernameNotFoundException(username);
  36.         }
  37.         List<SysPermission> permissionList = permissionService.findByUserId(sysUser.getId());
  38.         List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
  39.         if (!CollectionUtils.isEmpty(permissionList)) {
  40.             for (SysPermission sysPermission : permissionList) {
  41.                 authorityList.add(new SimpleGrantedAuthority(sysPermission.getCode()));
  42.             }
  43.         }
  44.         MyUser myUser = new MyUser(sysUser.getUsername(), passwordEncoder.encode(sysUser.getPassword()), authorityList);
  45.         log.info("登录成功!用户: {}", JSON.toJSONString(myUser));
  46.         return myUser;
  47.     }
  48. }

4.8. 验证

img

当我们看到这个界面的时候,表示认证服务器配置完成

5.两个客户端

5.1. Maven依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>org.springframework.boot</groupId>
  7.         <artifactId>spring-boot-starter-parent</artifactId>
  8.         <version>2.1.3.RELEASE</version>
  9.         <relativePath/> <!-- lookup parent from repository -->
  10.     </parent>
  11.     <groupId>com.cjs.sso</groupId>
  12.     <artifactId>oauth2-sso-client-member</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>oauth2-sso-client-member</name>
  15.     <description>Demo project for Spring Boot</description>
  16.     <properties>
  17.         <java.version>1.8</java.version>
  18.     </properties>
  19.     <dependencies>
  20.         <dependency>
  21.             <groupId>org.springframework.boot</groupId>
  22.             <artifactId>spring-boot-starter-data-jpa</artifactId>
  23.         </dependency>
  24.         <dependency>
  25.             <groupId>org.springframework.boot</groupId>
  26.             <artifactId>spring-boot-starter-oauth2-client</artifactId>
  27.         </dependency>
  28.         <dependency>
  29.             <groupId>org.springframework.boot</groupId>
  30.             <artifactId>spring-boot-starter-security</artifactId>
  31.         </dependency>
  32.         <dependency>
  33.             <groupId>org.springframework.security.oauth.boot</groupId>
  34.             <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  35.             <version>2.1.3.RELEASE</version>
  36.         </dependency>
  37.         <dependency>
  38.             <groupId>org.springframework.boot</groupId>
  39.             <artifactId>spring-boot-starter-thymeleaf</artifactId>
  40.         </dependency>
  41.         <dependency>
  42.             <groupId>org.thymeleaf.extras</groupId>
  43.             <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  44.             <version>3.0.4.RELEASE</version>
  45.         </dependency>
  46.         <dependency>
  47.             <groupId>org.springframework.boot</groupId>
  48.             <artifactId>spring-boot-starter-web</artifactId>
  49.         </dependency>
  50.         <dependency>
  51.             <groupId>com.h2database</groupId>
  52.             <artifactId>h2</artifactId>
  53.             <scope>runtime</scope>
  54.         </dependency>
  55.         <dependency>
  56.             <groupId>org.projectlombok</groupId>
  57.             <artifactId>lombok</artifactId>
  58.             <optional>true</optional>
  59.         </dependency>
  60.         <dependency>
  61.             <groupId>org.springframework.boot</groupId>
  62.             <artifactId>spring-boot-starter-test</artifactId>
  63.             <scope>test</scope>
  64.         </dependency>
  65.         <dependency>
  66.             <groupId>org.springframework.security</groupId>
  67.             <artifactId>spring-security-test</artifactId>
  68.             <scope>test</scope>
  69.         </dependency>
  70.     </dependencies>
  71.     <build>
  72.         <plugins>
  73.             <plugin>
  74.                 <groupId>org.springframework.boot</groupId>
  75.                 <artifactId>spring-boot-maven-plugin</artifactId>
  76.             </plugin>
  77.         </plugins>
  78.     </build>
  79. </project>

5.2. application.yml

  1. server:
  2.   port: 8082
  3.   servlet:
  4.     context-path: /memberSystem
  5. security:
  6.   oauth2:
  7.     client:
  8.       client-id: UserManagement
  9.       client-secret: user123
  10.       access-token-uri: http://localhost:8080/oauth/token
  11.       user-authorization-uri: http://localhost:8080/oauth/authorize
  12.     resource:
  13.       jwt:
  14.         key-uri: http://localhost:8080/oauth/token_key
img

这里context-path不要设成/,不然重定向获取code的时候回被拦截

5.3. WebSecurityConfig

  1. package com.cjs.example.config;
  2. import com.cjs.example.util.EnvironmentUtils;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  7. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  8. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  9. /**
  10.  * @author ChengJianSheng
  11.  * @date 2019-03-03
  12.  */
  13. @EnableOAuth2Sso
  14. @Configuration
  15. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  16.     @Autowired
  17.     private EnvironmentUtils environmentUtils;
  18.     @Override
  19.     public void configure(WebSecurity web) throws Exception {
  20.         web.ignoring().antMatchers("/bootstrap/**");
  21.     }
  22.     @Override
  23.     protected void configure(HttpSecurity http) throws Exception {
  24.         if ("local".equals(environmentUtils.getActiveProfile())) {
  25.             http.authorizeRequests().anyRequest().permitAll();
  26.         }else {
  27.             http.logout().logoutSuccessUrl("http://localhost:8080/logout")
  28.                     .and()
  29.                     .authorizeRequests()
  30.                     .anyRequest().authenticated()
  31.                     .and()
  32.                     .csrf().disable();
  33.         }
  34.     }
  35. }

说明:

  1. 最重要的注解是@EnableOAuth2Sso

  2. 权限控制这里采用Spring Security方法级别的访问控制,结合Thymeleaf可以很容易做权限控制

  3. 顺便多提一句,如果是前后端分离的话,前端需求加载用户的权限,然后判断应该显示那些按钮那些菜单

5.4. MemberController

  1. package com.cjs.example.controller;
  2. import org.springframework.security.access.prepost.PreAuthorize;
  3. import org.springframework.security.core.Authentication;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9. import java.security.Principal;
  10. /**
  11.  * @author ChengJianSheng
  12.  * @date 2019-03-03
  13.  */
  14. @Controller
  15. @RequestMapping("/member")
  16. public class MemberController {
  17.     @GetMapping("/list")
  18.     public String list() {
  19.         return "member/list";
  20.     }
  21.     @GetMapping("/info")
  22.     @ResponseBody
  23.     public Principal info(Principal principal) {
  24.         return principal;
  25.     }
  26.     @GetMapping("/me")
  27.     @ResponseBody
  28.     public Authentication me(Authentication authentication) {
  29.         return authentication;
  30.     }
  31.     @PreAuthorize("hasAuthority('member:save')")
  32.     @ResponseBody
  33.     @PostMapping("/add")
  34.     public String add() {
  35.         return "add";
  36.     }
  37.     @PreAuthorize("hasAuthority('member:detail')")
  38.     @ResponseBody
  39.     @GetMapping("/detail")
  40.     public String detail() {
  41.         return "detail";
  42.     }
  43. }

5.5. Order项目跟它是一样的

  1. server:
  2.   port: 8083
  3.   servlet:
  4.     context-path: /orderSystem
  5. security:
  6.   oauth2:
  7.     client:
  8.       client-id: OrderManagement
  9.       client-secret: order123
  10.       access-token-uri: http://localhost:8080/oauth/token
  11.       user-authorization-uri: http://localhost:8080/oauth/authorize
  12.     resource:
  13.       jwt:
  14.         key-uri: http://localhost:8080/oauth/token_key

5.6. 关于退出

退出就是清空用于与SSO客户端建立的所有的会话,简单的来说就是使所有端点的Session失效,如果想做得更好的话可以令Token失效,但是由于我们用的JWT,故而撤销Token就不是那么容易,关于这一点,在官网上也有提到:

本例中采用的方式是在退出的时候先退出业务服务器,成功以后再回调认证服务器,但是这样有一个问题,就是需要主动依次调用各个业务服务器的logout

6.工程结构

附上源码:https://github.com/chengjiansheng/cjs-oauth2-sso-demo.git

7. 演示

8.参考

https://www.cnblogs.com/cjsblog/p/9174797.html

https://www.cnblogs.com/cjsblog/p/9184173.html

https://www.cnblogs.com/cjsblog/p/9230990.html

https://www.cnblogs.com/cjsblog/p/9277677.html

https://blog.csdn.net/fooelliot/article/details/83617941

http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/

https://www.cnblogs.com/lihaoyang/p/8581077.html

https://www.cnblogs.com/charlypage/p/9383420.html

http://www.360doc.com/content/18/0306/17/16915_734789216.shtml

https://blog.csdn.net/chenjianandiyi/article/details/78604376

https://www.baeldung.com/spring-security-oauth-jwt

https://www.baeldung.com/spring-security-oauth-revoke-tokens

https://www.reinforce.cn/t/630.html

9.文档

https://projects.spring.io/spring-security-oauth/docs/oauth2.html

https://docs.spring.io/spring-security-oauth2-boot/docs/2.1.3.RELEASE/reference/htmlsingle/

https://docs.spring.io/spring-security-oauth2-boot/docs/2.1.3.RELEASE/

https://docs.spring.io/spring-security-oauth2-boot/docs/

https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/

https://docs.spring.io/spring-boot/docs/

https://docs.spring.io/spring-framework/docs/

https://docs.spring.io/spring-framework/docs/5.1.4.RELEASE/

https://spring.io/guides/tutorials/spring-boot-oauth2/

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#core-services-password-encoding

https://spring.io/projects/spring-cloud-security

https://cloud.spring.io/spring-cloud-security/single/spring-cloud-security.html

https://docs.spring.io/spring-session/docs/current/reference/html5/guides/java-security.html

https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html#boot-spring-configuration

点击阅读全文前往微服务电商教程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/68981
推荐阅读
相关标签
  

闽ICP备14008679号