MySecurityConfiguration.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package com.gihon.configSecurity.config;
  2. import com.gihon.configSecurity.encoder.MyPasswordEncoder;
  3. import com.gihon.configSecurity.handler.MyAccessDeniedHandler;
  4. import com.gihon.configSecurity.handler.MyFailureHandler;
  5. import com.gihon.configSecurity.handler.MySuccessHandler;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  11. import org.springframework.security.core.userdetails.UserDetailsService;
  12. import org.springframework.security.crypto.password.PasswordEncoder;
  13. import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
  14. import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
  15. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  16. import javax.sql.DataSource;
  17. /**
  18. * SpringSecurity的配置类型
  19. * 继承父类型WebSecurityConfigurerAdapter
  20. * WebSecurityConfigurerAdapter是一个Security提供的配置模板,可以快速实现
  21. * Security配置,简化自定义配置的复杂度。
  22. *
  23. * SpringSecurity提供的默认环境,如:登录页面、登录处理请求(/login)、拦截处理(未登录访问其他地址自动跳转到登录页面)
  24. * 只有在不提供自定义Security配置的时候,才有效。
  25. *
  26. * Security要求自定义的UserDetailsService配置配套提供一个PasswordEncoder类型的对象,
  27. * 对象中提供密码的加密和匹配逻辑,为认证提供加密处理。
  28. * 如果spring环境中没有PasswordEncoder类型的对象,UserDetailsService类型的对象无效。
  29. */
  30. @Configuration
  31. public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
  32. /**
  33. * 在Security中,处理认证逻辑的具体代码,不需要提供控制器逻辑。
  34. * 因为Security根据配置formLogin().loginProcessingUrl()自动做控制跳转。
  35. * 跳转逻辑是:
  36. * 找UserDetailsService接口的实现类型对象,调用启动的方法loadUserByUsername,实现登录认证。
  37. * @param http
  38. * @throws Exception
  39. */
  40. @Override
  41. protected void configure(HttpSecurity http) throws Exception {
  42. // 设置登录页面路径地址是 '/'
  43. // http.formLogin() // 获取Security中专门用来配置登录相关逻辑的配置类型
  44. // .usernameParameter("name") // 设置请求参数中,用户名的参数名称
  45. // .passwordParameter("pswd") // 设置请求参数中,密码的参数名称
  46. // .loginPage("/") // 配置登录页面请求地址是什么。
  47. //.loginProcessingUrl("/login") // 使用POST访问,访问什么地址的时候,实现认证逻辑。登录地址。
  48. // 认证成功或失败,Security会转发请求,到指定的地址。转发的请求是POST方式的。需要定义控制器处理。
  49. // .successForwardUrl("/success") // 登录成功后,跳转地址。 请求转发, 重复登录。
  50. // .defaultSuccessUrl("/success") // 登录成功后,重定向到指定位置
  51. // .successHandler(new MySuccessHandler("/security/success")) // 登录成功后,自定义处理逻辑。
  52. // .failureForwardUrl("/fail"); // 登录失败后,跳转地址
  53. // .failureUrl("/fail"); // 登录失败后,响应重定向
  54. // .failureHandler(new MyFailureHandler("/security/fail")); // 登录失败后,自定义处理逻辑
  55. /**
  56. * 设置权限相关
  57. * 可以通过对ExpressionUrlAuthorizationConfigurer配置,实现对URL地址的权限管理。
  58. * 可以定义针对固定地址、表达式地址的权限控制。
  59. * 常用权限控制方法:
  60. * 1、 permitAll() - 全权限访问,任意客户端都可访问。
  61. * 2、 authenticated() - 必须认证后才能访问。登录后才能访问。
  62. * 3、 denyAll() - 无访问权限。 没有登录的时候,要求登录;登录后,显示403无访问权限错误。
  63. * 4、 anonymous() - 匿名访问。可以不登录就访问的资源。和permitAll类似。
  64. * 5、 rememberMe() - 记住我。当认证的时候,开启了rememberMe功能,可以使用记住我访问。
  65. * 6、 fullyAuthenticated() - 完整认证才可访问。 rememberMe不能访问。
  66. *
  67. * 联合使用:
  68. * 如: antMatchers("/", "/index").permitAll(); 请求 "/" 或 "/index" 的时候,授予所有权限。
  69. * 基于角色和权限的访问控制:
  70. * 必须建立在已认证的基础上,才会执行对应的访问控制。
  71. * 1、 基于角色的访问控制:
  72. * URL匹配().hasRole | hasAnyRole
  73. * hasRole(String role) - 判断已登录的用户权限集合中,是否包含参数角色
  74. * 底层是调用的access("hasRole('ROLE_"+role+"')")
  75. * hasAnyRole(String... roles) - 判断已登录的用户权限集合中,是否包括参数中的任意角色。
  76. * 底层是调用的access("hasAnyRole('ROLE_角色1','ROLE_角色2'....)")
  77. * 2、 基于权限的访问控制:
  78. * hasAuthority(String authority) - 判断已登录的用户权限集合中,是否包含权限
  79. * 底层: access("hasAuthority('权限')")
  80. * hasAnyAuthority(String... authorities) - 判断已登录的用户权限集合中,是否包含参数中任意权限
  81. * 底层: access("hasAnyAuthority('权限1','权限2'....)")
  82. * 3、 基于IP的访问控制:
  83. * hasIpAddress(String ipAddress) 检查客户端IP是否是参数指定的IP
  84. * 客户端IP是: HttpServletRequest.getRemoteAddr()方法的返回值。
  85. * 底层: access("hasIpAddress('IP地址')")
  86. */
  87. http.authorizeRequests() // 获取Security中专门配置权限管理的配置类型
  88. .antMatchers("/login").permitAll()
  89. .antMatchers("/doc.html","/webjars/**","/img.icons/**","/swagger-resources/**","/v2/api-docs").permitAll()
  90. // .antMatchers("/", "/fail").permitAll() // 访问 '/' 地址的时候,不需要登录。
  91. // .antMatchers("/**/*.js").permitAll() // 只处理js文件
  92. // .regexMatchers(".+[.]css").permitAll() // 只处理css
  93. // .antMatchers("/anonymous").anonymous() // 匿名访问
  94. // .antMatchers("/denyAll").denyAll() // 不能访问
  95. // .antMatchers("/hasAdminRole").hasRole("管理员") // 判断有没有"管理员"角色
  96. // .antMatchers("/hasUserRole").hasRole("普通用户") // 判断有没有"普通用户"角色
  97. // .antMatchers("/hasAnyRole").hasAnyRole("管理员", "普通用户") // 判断是否包含管理员或普通用户角色。
  98. // .antMatchers("/hasAuthority").hasAuthority("userManagement")
  99. // .antMatchers("/hasAnyAuthority").hasAnyAuthority("userManagement","selfManagement")
  100. // .antMatchers("/accessRole").access("hasRole('ROLE_管理员')")// 使用access,角色控制
  101. // .antMatchers("/accessAuthority").access("hasAuthority('selfManagement')")// 使用access,权限控制
  102. // WebSecurityExpressionRoot
  103. //.antMatchers("/*").access("@myPermissionsMatcherImpl.hasPermission(request,authentication)")
  104. .anyRequest().authenticated(); // 所有的请求地址,都必须登录才能访问。
  105. // 异常处理配置
  106. http.exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler());
  107. // 配置rememberMe, 使用rememberMe功能的时候,认证成功结果跳转,一定要使用重定向。
  108. http.rememberMe()
  109. .rememberMeParameter("rememberMe") // 设置请求参数名,默认为remember-me
  110. .rememberMeCookieName("rememberMe") // 设置记住我的cookie名称。默认为remember-me
  111. .tokenValiditySeconds(300) // 设置rememberMe有效时长。默认14天。
  112. .userDetailsService(userLoginServiceImpl) // 设置用户认证逻辑对象
  113. .tokenRepository(tokenRepository); // 设置rememberMe数据持久化对象。持久化用户认证成功后的主体。
  114. // 退出配置, 注销配置
  115. http.logout()
  116. .invalidateHttpSession(true) // 退出的时候,销毁HttpSession对象。默认true
  117. .clearAuthentication(true) // 退出的时候,清空已认证用户主体对象。默认true
  118. .logoutUrl("/security/logout") // 退出登录的请求地址。默认是 /logout
  119. .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
  120. .logoutSuccessUrl("/security/"); // 退出后的跳转地址,重定向。 默认是 loginPage?logout
  121. // csrf安全处理, 关闭csrf。 防止恶意攻击的技术。 security4+ 默认开启的。
  122. http.csrf().disable();
  123. }
  124. // @Autowired
  125. // private DataSource dataSource;
  126. // rememberMe数据保存对象,相当于是DAO
  127. @Bean
  128. public PersistentTokenRepository persistentTokenRepository(DataSource dataSource){
  129. // 使用Spring-JDBC技术,实现rememberMe数据的存储。保存到数据库。
  130. // 在JdbcTokenRepositoryImpl类型的对象中,必须提供一个DataSource对象。
  131. JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
  132. jdbcTokenRepository.setDataSource(dataSource);
  133. // rememberMe表格的创建, 只能在系统第一次启动的时候创建。 默认是false,不会启动创建表格。
  134. // jdbcTokenRepository.setCreateTableOnStartup(true);
  135. return jdbcTokenRepository;
  136. }
  137. @Autowired
  138. private UserDetailsService userLoginServiceImpl;
  139. @Autowired
  140. private PersistentTokenRepository tokenRepository;
  141. // 传递的构造参数BCryptPasswordEncoder(int strength), 建议为8的整数倍。
  142. @Bean
  143. public PasswordEncoder passwordEncoder(){
  144. return new MyPasswordEncoder();
  145. }
  146. }