当前位置:   article > 正文

基于SpringSecurityOAuth2实现单点登录, 简单示例用于学习SpringSecurityOAuth2. 解决了遇到的所有SpringSecurityOAuth2的坑_springsecurity6-oauth2 客户端

springsecurity6-oauth2 客户端

概述

基于SpringSecurityOAuth2实现单点登录, 简单示例用于学习SpringSecurityOAuth2. 解决了遇到的所有SpringSecurityOAuth2的坑。添加了注销登录,扩展了短信登录, 验证码等功能,实现了Vue前后端分离情况下的OAuth2单点登录。 麻雀虽小五脏俱全,满足企业级应用.

详细

一、需求(要做什么)

1.基于SpringSecurityOAuth2实现单点登录,实现基于SpringSecurityOAuth2的客户端对接认证中心, 实现基于OAuth2协议的原始方法对接认证中心, 基于vue前后端分离的方式对接认证中心。

2.编写基于oauth2认证的4种认证模式的demo, 让初学者一看就懂。 

3.实现登陆,登录通过账户密码登录, 也可通过手机验证码登录, 实现记住我,十天免登陆功能。

4.实现注销登录。

二、理论概述

        OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。 这是一个标准, spring也推荐也默认采用这种登录授权的模式, 所以跟着spring来,方向不会错。

        OAuth 的核心就是向第三方应用颁发令牌,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。

        OAuth 2.0 规定了四种获得令牌的流程:

            authorization code(授权码模式)

            implicit(简化模式)

            resource owner password credentials(密码模式)

            client credentials(客户端模式)

        授权码模式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用, 目前阿里,腾讯等大型互联网公司,甚至一些政府项目等都用这种方式, 看来不学不行了。

        

三、代码分析

1.首先引入pom

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.security.oauth</groupId>
  7. <artifactId>spring-security-oauth2</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.security.oauth.boot</groupId>
  11. <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.security</groupId>
  15. <artifactId>spring-security-jwt</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>com.nimbusds</groupId>
  19. <artifactId>nimbus-jose-jwt</artifactId>
  20. </dependency>

2.  认证中心的核心代码

  1. @Configuration
  2. @EnableWebSecurity
  3. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Autowired
  5. private DataSource dataSource;
  6. @Bean
  7. public PersistentTokenRepository persistentTokenRepository() {
  8. JdbcTokenRepositoryImpl tokenRepository=new JdbcTokenRepositoryImpl();
  9. tokenRepository.setDataSource(dataSource);
  10. //第一次创建开启
  11. //tokenRepository.setCreateTableOnStartup(true);
  12. return tokenRepository;
  13. }
  14. @Autowired
  15. SsoUserDetailsServiceImpl myUserDetailsService;
  16. @Autowired
  17. SsoSavedRequestAwareAuthenticationSuccessHandler myOwnSavedRequestAwareAuthenticationSuccessHandler;
  18. @Autowired
  19. SsoAuthenticationFailureHandler myAuthenticationFailureHandler;
  20. @Autowired
  21. SsoLogoutSuccessHandler myLogoutSuccessHandler;
  22. @Autowired
  23. ValidateCodeFilterSecurityConfiguration validateCodeFilterSecurityConfiguration;
  24. @Autowired
  25. LoginFormSecurityConfiguration loginFormSecurityConfiguration;
  26. @Override
  27. protected void configure(HttpSecurity http) throws Exception {
  28. //跨站请求伪造
  29. http.csrf().disable();
  30. //解决iframe问题
  31. http.headers().frameOptions().disable();
  32. http
  33. .apply(validateCodeFilterSecurityConfiguration)
  34. .and()
  35. // .addFilterBefore(parametersFilter, UsernamePasswordAuthenticationFilter.class)
  36. //表单登录
  37. .formLogin()
  38. //自定义登陆的页面
  39. .loginPage("/authentication/require")
  40. //指定登陆action 的 url
  41. .loginProcessingUrl("/authentication/form")
  42. //登录成功处理
  43. .successHandler(myOwnSavedRequestAwareAuthenticationSuccessHandler)
  44. //登出失败处理
  45. .failureHandler(myAuthenticationFailureHandler)
  46. .and()
  47. .rememberMe()
  48. .tokenRepository(persistentTokenRepository())
  49. .tokenValiditySeconds(3600)
  50. .userDetailsService(myUserDetailsService)
  51. .and()
  52. //请求认证模块 所有请求都需要认证
  53. .authorizeRequests()
  54. .antMatchers("/authentication/require",
  55. "/authentication/form",
  56. "/logout",
  57. "/login",
  58. "/login/time",
  59. "/getBackPasswordIndex",
  60. "/register",
  61. "/code/image",
  62. "/code/sms",
  63. "/error",
  64. "/oauth/exit",
  65. "/oauth/authorize/**",
  66. "/oauth/token/**",
  67. "/auth/oauth/token/**",
  68. "/oauth/check_token/**",
  69. "/oauth/confirm_access/**",
  70. "/oauth/error/**",
  71. "/images/**",
  72. "/plugin/**",
  73. "/js/**",
  74. "/css/**").permitAll()
  75. //所有请求认证
  76. .anyRequest().authenticated()
  77. .and()
  78. .logout()
  79. .logoutUrl("/logout")
  80. .logoutSuccessHandler(myLogoutSuccessHandler)
  81. .and()
  82. .apply(loginFormSecurityConfiguration);
  83. }
  84. @Bean
  85. public PasswordEncoder passwordEncoder() {
  86. return new BCryptPasswordEncoder();
  87. }
  88. /**
  89. * session过期
  90. * @return
  91. */
  92. @Bean
  93. public HttpSessionEventPublisher httpSessionEventPublisher() {
  94. return new HttpSessionEventPublisher();
  95. }
  96. }
  1. /**
  2. * DefaultTokenServices 实现了ConsumerTokenServices接口, revokeToken方法定义了删除token的方法
  3. */
  4. @Autowired
  5. @Qualifier("consumerTokenServices")
  6. private ConsumerTokenServices consumerTokenServices;
  7. @RequestMapping("/remove/token")
  8. public void removeToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
  9. String tokenValue = request.getParameter("access_token");
  10. String redirectUri = request.getParameter("redirect_uri");
  11. consumerTokenServices.revokeToken(tokenValue);
  12. // 清除记住我的数据
  13. request.getSession().invalidate();
  14. response.sendRedirect(redirectUri);
  15. }

3. 客户端的核心代码

  1. @Configuration
  2. @EnableOAuth2Sso
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Autowired
  5. MyLogoutSuccessHandler myLogoutSuccessHandler;
  6. @Override
  7. protected void configure(HttpSecurity http) throws Exception {
  8. //跨站请求伪造
  9. http.csrf().disable();
  10. //解决iframe问题
  11. http.headers().frameOptions().disable();
  12. http.antMatcher("/**")
  13. .authorizeRequests()
  14. .antMatchers("/login**","/logout/**","/js/**","/outer/**").permitAll()
  15. .anyRequest()
  16. .authenticated()
  17. .and()
  18. .logout()
  19. .logoutUrl("/logout")
  20. .logoutSuccessHandler(myLogoutSuccessHandler);
  21. super.configure(http);
  22. }
  23. /**
  24. * session过期
  25. * @return
  26. */
  27. @Bean
  28. public HttpSessionEventPublisher httpSessionEventPublisher() {
  29. return new HttpSessionEventPublisher();
  30. }
  31. }
四、项目文件结构截图

image.png

五、启动部署流程

1. 首先 在mysql创建数据库sso-oauth,在数据库执行sqlj脚本: sso-oauth-parent/sql/sso-oauth.sql

2. 然后用idea导入maven项目sso-oauth-parent, 待pom依赖jar包下载完成后执行下一步。

3. 配置redis

解压 so-oauth-parent\Redis-x64-3.0.504.zip 

双击 redis-server.exe   启动redis

image.png

image.png

4. 启动认证中心 , 启动client1, client2, client3 

image.png

其余client项目类似

4. 编译启动vue-demo( 如果没有前后端分离vue认证需求, 可以忽略本步。

要想启动vue项目,  首先安装nodejs环境 和vue环境,  比较简单参考百度

接下来进入:  sso-oauth-parent\vue-demo 目录, 执行cmd命令

npm install   # 安装vue依赖

npm install jquery   #安装jquery插件

npm run serve 启动服务

成功启动看到如下

image.png

六、演示效果

认证中心登录界面:

image.png

auth-center主页

image.png

无登录跳转client1主页

image.png

无登录跳转client2主页

image.png

无登录跳转client3-vue主页

image.png

退出登录

image.png

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

闽ICP备14008679号