我们在使用spring sec的时候, 一般会继承WebSecurityConfigurerAdapter类 ,然后选择覆盖protected void configure(AuthenticationManagerBuilder auth)和protected void configure(HttpSecurity http)方法

  @Autowired
    private AuthenticationProviderService authenticationProvider;
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    @Bean
    public SCryptPasswordEncoder sCryptPasswordEncoder() {
        return new SCryptPasswordEncoder();
//登录认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
//登录拦截模式配置
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/**").authenticated()
        .and()
        .formLogin().loginPage("/login").permitAll()
        .successHandler(new MySavedRequestAwareAuthenticationSuccessHandler())
        .failureHandler(new SimpleUrlAuthenticationFailureHandler())
        .and()
        .logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))
        .and()
        .exceptionHandling().authenticationEntryPoint(new Http401AuthenticationEntryPoint("login first"))
        .accessDeniedHandler(new AccessDeniedHandlerImpl());

Spring Security 中用户对象相关类结构图
在这里插入图片描述

一般登录的拦截 一般重写 protected void configure(HttpSecurity http) 方法,登录用户的认证我们一般,重写 protected void configure(AuthenticationManagerBuilder auth) 方法

登录用户的认证

简要说明
AuthenticationManager :认证是由 AuthenticationManager 来管理的,但是真正进行认证的是 AuthenticationManager 中定义的 AuthenticationProvider。AuthenticationManager 中可以定义有多个 AuthenticationProvider;

AuthenticationProvider :认证管理的逻辑实现类,当我们需要实现自己的认证逻辑的时候需要实现此接口,重写 public Authentication authenticate(Authentication authentication) 方法;

UserDetailsService :用户操作相关的接口类,当我们想要从数据库中查询用户的信息的时候需要实现实现此接口查询用户信息;

认证是由 AuthenticationManager 来管理的,但是真正进行认证的是 AuthenticationManager 中定义的 AuthenticationProvider。AuthenticationManager 中可以定义有多个 AuthenticationProvider。当我们使用 authentication-provider 元素来定义一个 AuthenticationProvider 时需要实现AuthenticationProvider接口,如果没有指定对应关联的 AuthenticationProvider 对象,Spring Security 默认会使用 DaoAuthenticationProvider。DaoAuthenticationProvider 在进行认证的时候需要一个 UserDetailsService 来获取用户的信息 UserDetails,其中包括用户名、密码和所拥有的权限等。所以如果我们需要改变认证的方式,我们可以实现自己的 AuthenticationProvider;如果需要改变认证的用户信息来源,我们可以实现 UserDetailsService。

实现了自己的 AuthenticationProvider 之后,我们可以在配置文件中这样配置来使用我们自己的 AuthenticationProvider。其中 myAuthenticationProvider 就是我们自己的 AuthenticationProvider 实现类对应的 bean。

   <security:authentication-manager>
      <security:authentication-provider ref="myAuthenticationProvider"/>
   </security:authentication-manager>

实现了自己的 UserDetailsService 之后,我们可以在配置文件中这样配置来使用我们自己的 UserDetailsService。其中的 myUserDetailsService 就是我们自己的 UserDetailsService 实现类对应的 bean。

   <security:authentication-manager>
      <security:authentication-provider user-service-ref="myUserDetailsService"/>
   </security:authentication-manager>

使用 jdbc-user-service 获取
在 Spring Security 的命名空间中在 authentication-provider 下定义了一个 jdbc-user-service 元素,通过该元素我们可以定义一个从数据库获取 UserDetails 的 UserDetailsService。jdbc-user-service 需要接收一个数据源的引用。

   <security:authentication-manager>
      <security:authentication-provider>
         <security:jdbc-user-service data-source-ref="dataSource"/>      
      </security:authentication-provider>
   </security:authentication-manager>

Spring Security 中认证的对象相关类结构图 ,具体关系如下图
在这里插入图片描述

重写用户认证逻辑需要实现接口AuthenticationProvider ,重写 Authentication authenticate(Authentication authentication) 方法

package com.lagou.springsecurity.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.lagou.springsecurity.user.model.CustomUserDetails;
@Service
public class AuthenticationProviderService implements AuthenticationProvider {
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    private SCryptPasswordEncoder




    
 sCryptPasswordEncoder;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        //根据用户名从数据库中获取CustomUserDetails
        CustomUserDetails user = userDetailsService.loadUserByUsername(username);
        //根据所配置的密码加密算法来分别验证用户密码
        switch (user.getUser().getPasswordEncoderType()) {
            case BCRYPT:
                return checkPassword(user, password, bCryptPasswordEncoder);
            case SCRYPT:
                return checkPassword(user, password, sCryptPasswordEncoder);
        throw new  BadCredentialsException("Bad credentials");
    @Override
    public boolean supports(Class<?> aClass) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    private Authentication checkPassword(CustomUserDetails user, String rawPassword, PasswordEncoder encoder) {
        if (encoder.matches(rawPassword, user.getPassword())) {
            return new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
        } else {
            throw new BadCredentialsException("Bad credentials");

重写用户的查询逻辑需要实现接口UserDetailsService

package com.lagou.springsecurity.service;
import com.lagou.springsecurity.domain.User;
import com.lagou.springsecurity.repository.UserRepository;
import com.lagou.springsecurity.user.model.CustomUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.function.Supplier;
@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    @Override
    public CustomUserDetails loadUserByUsername(String username) {
        Supplier<UsernameNotFoundException> s =
                () -> new UsernameNotFoundException("Username" + username + "is invalid!");
        User u = userRepository.findUserByUsername(username).orElseThrow(s);
        return new CustomUserDetails(u);

Spring Security 中的用户对象
Spring Security 中的用户对象用来描述用户并完成对用户信息的管理,涉及UserDetails、GrantedAuthority、UserDetailsService 和 UserDetailsManager这四个核心对象。

UserDetails:描述 Spring Security 中的用户。
GrantedAuthority:定义用户的操作权限。
UserDetailsService:定义了对 UserDetails 的查询操作。
UserDetailsManager:扩展 UserDetailsService,添加了创建用户、修改用户密码等功能。

这四个对象之间的关联关系如下图所示,显然,对于由 UserDetails 对象所描述的一个用户而言,它应该具有 1 个或多个能够执行的 GrantedAuthority:

Spring Security 中的四大核心用户对象

结合上图,我们先来看承载用户详细信息的 UserDetails 接口,如下所示:

public interface UserDetails extends Serializable {
    //获取该用户的权限信息
    Collection<? extends GrantedAuthority> getAuthorities();
    //获取密码
	String getPassword();
	//获取用户名
    String getUsername();
	//判断该账户是否已失效
    boolean isAccountNonExpired();
    //判断该账户是否已被锁定
    boolean isAccountNonLocked();
    //判断该账户的凭证信息是否已失效
    boolean isCredentialsNonExpired();
    //判断该用户是否可用
    boolean isEnabled();

通过 UserDetails,我们可以获取用户相关的基础信息,并判断其当前状态。同时,我们也可以看到 UserDetails 中保存着一组 GrantedAuthority 对象。而 GrantedAuthority 指定了一个方法用来获取权限信息,如下所示:

public interface GrantedAuthority extends Serializable {
    //获取权限信息
    String getAuthority();

UserDetails 存在一个子接口 MutableUserDetails,从命名上不难看出后者是一个可变的 UserDetails,而可变的内容就是密码。MutableUserDetails 接口的定义如下所示:

interface MutableUserDetails extends UserDetails {
    //设置密码
    void setPassword(String password);

如果我们想要在应用程序中创建一个 UserDetails 对象,可以使用如下所示的链式语法:

UserDetails user = User.withUsername("jianxiang") 
  .password("123456") 
  .authorities("read", "write") 
  .accountExpired(false) 
  .disabled(true) 
  .build();

Spring Security 还专门提供了一个 UserBuilder 对象来辅助构建 UserDetails,使用方式也类似:

User.UserBuilder builder = 
	User.withUsername("jianxiang");
UserDetails user = builder
  .password("12345") 
  .authorities("read", "write")
  .accountExpired(false) 
  .disabled(true) 
  .build();

在 Spring Security 中,针对 UserDetails 专门提供了一个 UserDetailsService,该接口用来管理 UserDetails,定义如下:

public interface UserDetailsService {
    //根据用户名获取用户信息
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

而 UserDetailsManager 继承了 UserDetailsService,并提供了一批针对 UserDetails 的操作接口,如下所示:

public interface UserDetailsManager extends UserDetailsService {
    //创建用户
    void createUser(UserDetails user);
    //更新用户
    void updateUser(UserDetails user);
    //删除用户
    void deleteUser(String username);
    //修改密码
    void changePassword(String oldPassword, String newPassword);
    //判断指定用户名的用户是否存在
    boolean userExists(String username);
                    我们在使用spring sec的时候,一般会继承WebSecurityConfigurerAdapter类,然后选择覆盖protected void configure(AuthenticationManagerBuilder auth)和protected void configure(HttpSecurity http)方法  @Autowired    private AuthenticationProviderService authenticationProvider;    @Bean
核心 -  spring-security-core.jar 25
远程处理 - spring-security-remoting.jar 25
Web - spring-security-web.jar 25
配置 - spring-security-config.jar 26
LDAP - spring-security-ldap.jar 26
ACL - spring-security-acl.jar 26
CAS - spring-security-cas.jar 26
OpenID - spring-security-openid.jar 26
测试 - spring-security-test.jar 26
2.4.4检出来源 26
3. Spring Security 4.2的新特性 27
3.1 Web改进 27
3.2配置改进 28
3.3杂项 28
4.样品和指南(从这里开始) 28
5. Java配置 29
5.1 Hello Web安全Java配置 29
5.1.1 AbstractSecurityWebApplicationInitializer 31
5.1.2 AbstractSecurityWebApplicationInitializer不存在Spring 31
5.1.3使用Spring MVC的AbstractSecurityWebApplicationInitializer 32
5.2 HttpSecurity 32
5.3 Java配置和表单登录 34
5.4授权请求 35
5.5处理注销 36
5.5.1 LogoutHandler 37
5.5.2 LogoutSuccessHandler 37
5.5.3更多注销相关参考 38
5.6认证 38
5.6.1内存认证 38
5.6.2 JDBC认证 39
5.6.3 LDAP认证 39
5.6.4 AuthenticationProvider 41
5.6.5 UserDetailsService 41
5.6.6 LDAP认证 41
5.7多个HttpSecurity 41
5.8方法安全性 43
5.8.1 EnableGlobalMethodSecurity 43
5.8.2 GlobalMethodSecurityConfiguration 44
5.9后处理配置的对象 45
5.10自定义DSL 46
6.安全命名空间配置 47
6.1简介 47
6.1.1命名空间的设计 49
6.2安全命名空间配置入门 50
6.2.1 web.xml配置 50
6.2.2最小的配置 50
6.2.3表单和基本登录选项 52
设置默认的登录目的地 54
6.2.4注销处理 54
6.2.5使用其他身份验证提供程序 55
添加密码编码器 56
6.3高级Web功能 56
6.3.1记得我认证 56
6.3.2添加HTTP / HTTPS通道安全 57
6.3.3会话管理 57
检测超时 57
并发会话控制 58
会话固定攻击保护 59
6.3.4 OpenID支持 60
属性交换 61
6.3.5响应头 62
6.3.6添加你自己的过滤器 62
设置一个自定义的AuthenticationEntryPoint 64
6.4方法安全 64
6.4.1 元素 65
使用protect-pointcut添加安全性切入点 66
6.5默认AccessDecisionManager 67
6.5.1自定义AccessDecisionManager 67
6.6验证管理器和命名空间 67
7.示例应用程序 69
7.1教程示例 69
7.2联系人 69
7.3 LDAP样本 71
7.4 OpenID示例 71
7.5 CAS样品 71
7.6 JAAS样品 72
7.7预认证样本 72
8. Spring Security社区 72
8.1问题跟踪 72
8.2成为参与 73
8.3更多信息 73
第二部分 架构与实现 73
9.技术概述 73
9.1运行环境 73
9.2核心组件 74
9.2.1 SecurityContextHolder,SecurityContext和认证对象 74
获取有关当前用户的信息 75
9.2.2 UserDetailsService 75
9.2.3授予权力 77
9.2.4总结 77
9.3认证 78
9.3.1什么是Spring Security中的认证? 78
9.3.2直接设置SecurityContextHolder内容 80
9.4 Web应用程序中的身份验证 81
9.4.1 ExceptionTranslationFilter 82
9.4.2 AuthenticationEntryPoint 82
9.4.3认证机制 82
9.4.4在请求之间存储SecurityContext 83
9.5 Spring Security中的访问控制(授权) 84
9.5.1安全和AOP建议 84
9.5.2安全对象和AbstractSecurityInterceptor 85
什么是配置属性? 85
RunAsManager 86
AfterInvocationManager 86
扩展安全对象模型 87
9.6本地化 87
10.核心服务 89
10.1 AuthenticationManager,ProviderManager和AuthenticationProvider 89
10.1.1成功认证时清除证书 91
10.1.2 DaoAuthenticationProvider 91
10.2 UserDetailsService实现 92
10.2.1内存认证 92
10.2.2 JdbcDaoImpl 93
权威组织 94
10.3密码编码 94
10.3.1什么是散列? 95
10.3.2添加盐到哈希 95
10.3.3散列和认证 96
10.4Jackson 支持 96
第三部分 测试 97
11.测试方法安全性 97
11.1安全测试设置 98
11.2 @WithMockUser 98
11.3 @WithAnonymousUser 100
11.4 @用户详细信息 101
11.5 @WithSecurityContext 102
11.6测试元注释 104
12. Spring MVC测试集成 104
12.1设置MockMvc和Spring Security 104
12.2 SecurityMockMvcRequestPostProcessors 105
12.2.1使用CSRF保护进行测试 105
12.2.2在Spring MVC测试中以用户身份运行测试 106
12.2.3使用RequestPostProcessor在Spring MVC测试中以用户身份运行 106
作为用户在Spring MVC测试中使用注释运行 108
12.2.4测试HTTP基本认证 109
12.3 SecurityMockMvcRequestBuilders 109
12.3.1测试基于表单的认证 109
12.3.2测试注销 110
12.4 SecurityMockMvcResultMatchers 110
12.4.1未经认证的声明 111
12.4.2认证断言 111
第四部分 Web应用程序安全 112
13.安全过滤器链 112
13.1 DelegatingFilterProxy 112
13.2 FilterChainProxy 113
13.2.1绕过滤网链 115
13.3过滤器排序 115
13.4请求匹配和HttpFirewall 116
13.5与其他基于过滤器的框架一起使用 118
13.6高级命名空间配置 118
14.核心安全筛选器 119
14.1 FilterSecurityInterceptor 119
14.2 ExceptionTranslationFilter 121
14.2.1 AuthenticationEntryPoint 122
14.2.2 AccessDeniedHandler 122
14.2.3 SavedRequest和RequestCache接口 123
14.3 SecurityContextPersistenceFilter 123
14.3.1 SecurityContextRepository 124
14.4 UsernamePasswordAuthenticationFilter 125
14.4.1认证成功与失败的应用流程 125
15. Servlet API集成 127
15.1 Servlet 2.5+集成 127
15.1.1 HttpServletRequest.getRemoteUser() 127
15.1.2 HttpServletRequest.getUserPrincipal() 127
15.1.3 HttpServletRequest.isUserInRole(String) 128
15.2 Servlet 3+集成 128
15.2.1 HttpServletRequest.authenticate(HttpServletResponse) 128
15.2.2 HttpServletRequest.login(String,String) 129
15.2.3 HttpServletRequest.logout() 129
15.2.4 AsyncContext.start(Runnable) 129
15.2.5异步Servlet支持 130
15.3 Servlet 3.1+集成 131
15.3.1 HttpServletRequest#changeSessionId() 132
16.基本和摘要式身份验证 132
16.1 BasicAuthenticationFilter 132
16.1.1配置 132
16.2 DigestAuthenticationFilter 133
16.2.1配置 135
17.记住我的身份验证 136
17.1概述 136
17.2简单的基于哈希的令牌方法 136
17.3持久性令牌方法 137
17.4记住我的接口和实现 138
17.4.1 TokenBasedRememberMeServices 138
17.4.2 PersistentTokenBasedRememberMeServices 139
18.跨站点请求伪造(CSRF) 140
18.1 CSRF攻击 140
18.2同步器令牌模式 141
18.3何时使用CSRF保护 142
18.3.1 CSRF保护和JSON 142
18.3.2 CSRF和无状态浏览器应用程序 143
18.4使用Spring Security CSRF保护 143
18.4.1使用适当的HTTP动词 144
18.4.2配置CSRF保护 144
18.4.3包含CSRF令牌 145
表单提交 145
Ajax和JSON请求 145
CookieCsrfTokenRepository 146
18.5 CSRF警告 147
18.5.1超时 148
18.5.2登录 148
18.5.3注销 149
18.5.4多部分(文件上传) 149
在Spring Security之前放置MultipartFilter 150
包含CSRF令牌 151
18.5.5隐藏的HttpMethodFilter 151
18.6覆盖默认值 151
19. CORS 152
20.安全性HTTP响应头 154
20.1默认的安全头 154
20.1.1缓存控制 157
20.1.2内容类型选项 158
20.1.3 HTTP严格传输安全(HSTS) 159
20.1.4 HTTP公钥密码(HPKP) 161
20.1.5 X-Frame-Options 163
20.1.6 X-XSS保护 164
20.1.7内容安全策略(CSP) 165
配置内容安全策略 166
其他资源 168
20.1.8推荐人政策 168
配置引用者策略 169
20.2自定义标题 169
20.2.1静态头 169
20.2.2标题作者 170
20.2.3 DelegatingRequestMatcherHeaderWriter 171
21.会议管理 172
21.1 SessionManagementFilter 173
21.2 SessionAuthenticationStrategy 173
21.3并发控制 174
21.3.1查询当前通过身份验证的用户及其会话的SessionRegistry 176
22.匿名身份验证 177
22.1概述 177
22.2配置 178
22.3 AuthenticationTrustResolver 179
23. WebSocket安全 180
23.1 WebSocket配置 181
23.2 WebSocket身份验证 182
23.3 WebSocket授权 182
23.3.1 WebSocket授权说明 183
消息类型的WebSocket授权 184
目的地上的WebSocket授权 184
23.3.2出站消息 185
23.4执行相同的来源政策 185
23.4.1为什么同源? 185
23.4.2 Spring WebSocket允许的来源 186
23.4.3添加CSRF到Stomp头 186
23.4.4在WebSockets中禁用CSRF 187
23.5使用SockJS 187
23.5.1 SockJS和框架选项 187
23.5.2轻松放松CSRF 188
第五部分授权 190
24.授权体系结构 190
24.1当局 190
24.2预调用处理 191
24.2.1 AccessDecisionManager 191
24.2.2基于投票的AccessDecisionManager实现 192
RoleVoter 193
AuthenticatedVoter 194
自定义选民 194
24.3调用处理后 194
24.4分层角色 196
25.安全的对象实现 197
25.1 AOP联盟(MethodInvocation)安全拦截器 197
25.1.1显式MethodSecurityInterceptor配置 197
25.2 AspectJ(JoinPoint)安全拦截器 198
26.基于表达式的访问控制 200
26.1概述 200
26.1.1通用内置表达式 201
26.2网络安全表达式 202
26.2.1在Web安全表达式中引用Bean 203
26.2.2 Web安全表达式中的路径变量 204
26.3方法安全表达式 204
26.3.1 @Pre和@Post注释 205
访问控制使用@PreAuthorize和@PostAuthorize 205
使用@PreFilter和@PostFilter进行过滤 207
26.3.2内置表达式 207
PermissionEvaluator接口 208
方法安全元注释 209
第六部分 其他主题 209
27.域对象安全(ACL) 209
27.1概述 209
27.2重要概念 211
27.3入门 214
28.预认证方案 216
28.1预认证框架类 216
28.1.1 AbstractPreAuthenticatedProcessingFilter 217
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 217
28.1.2 PreAuthenticatedAuthenticationProvider 218
28.1.3 Http403ForbiddenEntryPoint 218
28.2具体实施 219
28.2.1请求头认证(Siteminder) 219
Siteminder示例配置 219
28.2.2 Java EE容器认证 220
29. LDAP认证 220
29.1概述 220
29.2在Spring Security中使用LDAP 221
29.3配置LDAP服务器 221
29.3.1使用嵌入式测试服务器 222
29.3.2使用绑定认证 222
29.3.3加载权限 223
29.4实现类 223
29.4.1 LdapAuthenticator实现 224
通用功能 224
认证者 225
PasswordComparisonAuthenticator 225
29.4.2连接到LDAP服务器 225
29.4.3 LDAP搜索对象 225
FilterBasedLdapUserSearch中 225
29.4.4 LdapAuthoritiesPopulator 226
29.4.5 Spring Bean配置 226
29.4.6 LDAP属性和定制的UserDetails 227
29.5 Active Directory认证 228
29.5.1 ActiveDirectoryLdapAuthenticationProvider 228
活动目录错误代码 229
30. JSP标签库 230
30.1声明Taglib 230
30.2授权标签 230
30.2.1禁用测试的标签授权 231
30.3认证标签 232
30.4 accesscontrollist标签 232
30.5 csrfInput标签 233
30.6 csrfMetaTags标签 233
31 Java认证和授权服务(JAAS)提供者 235
31.1概述 235
31.2摘要:Java认证提供者 235
31.2.1 JAAS CallbackHandler 235
31.2.2 JAAS权威机构 236
31.3 DefaultJaasAuthenticationProvider 237
31.3.1 InMemoryConfiguration 237
31.3.2 DefaultJaasAuthenticationProvider示例配置 238
31.4 JaasAuthenticationProvider 239
31.5作为主题运行 240
32. CAS认证 240
32.1概述 240
32.2 CAS的工作原理 240
32.2.1 Spring安全和CAS交互序列 241
32.3 CAS客户端的配置 244
32.3.1服务票据认证 244
32.3.2单一注销 246
32.3.3使用CAS认证无状态服务 249
配置CAS以获取代理授予票证 249
使用代理票证调用无状态服务 250
32.3.4代理票证认证 251
33. X.509认证 253
33.1概述 253
33.2将X.509身份验证添加到您的Web应用程序 253
33.3在Tomcat中设置SSL 254
34.运行认证替换 255
34.1概述 255
34.2配置 255
35. Spring Security加密模块 257
35.1简介 257
35.2加密器 257
35.2.1 BytesEncryptor 257
35.2.2 TextEncryptor 258
35.3关键发电机 258
35.3.1 BytesKeyGenerator 258
35.3.2 StringKeyGenerator 259
35.4密码编码 259
36.并发支持 260
36.1 DelegatingSecurityContextRunnable 260
36.2 DelegatingSecurityContextExecutor 262
36.3 Spring安全性并发类 264
37. Spring MVC集成 265
37.1 @EnableWebMvcSecurity 265
37.2 MvcRequestMatcher 265
37.3 @AuthenticationPrincipal 268
37.4 Spring MVC异步集成 271
37.5 Spring MVC和CSRF集成 271
37.5.1自动令牌包含 271
37.5.2解析CsrfToken 272
第七部分 Spring数据集成 273
38. Spring Data&Spring安全配置 273
39. @Query中的安全表达式 273
第八部分 附录 274
40.安全数据库模式 274
40.1用户模式 274
40.1.1集团当局 274
40.2持久登录(记得我)架构 275
40.3 ACL模式 275
40.3.1 HyperSQL 276
40.3.2 PostgreSQL 277
40.3.3 MySQL和MariaDB 278
40.3.4 Microsoft SQL Server 279
40.3.5 Oracle数据库 280
41.安全命名空间 282
41.1 Web应用程序安全性 282
41.1.1  282
41.1.2  282
属性 283
的子元素 285
41.1.3  286
的父元素 286
属性 286
41.1.4  286
属性 287
父元素 287
41.1.5 <headers> 287
<headers>属性 288
<headers>的父元素 288
<headers>的子元素 288
41.1.6  289
属性 289
的父元素 289
41.1.7  289
属性 289
的父元素 290
41.1.8  290
属性 290
的父元素 290
41.1.9  290
的子元素 290
41.1.10  291
属性 291
的父元素 291
41.1.11  291
属性 291
的父元素 291
41.1.12  291
属性 292
的父元素 292
41.1.13 <frame-options> 292
<frame-options>属性 292
<frame-options>的父元素 293
41.1.14 [removed] 293
[removed]属性 293
[removed]的父元素 294
41.1.15  294
属性 294
的父元素 294
41.1.16 <header> 294
<header-attributes>属性 294
<header>的父元素 295
41.1.17  295
的父元素 295
属性 295
41.1.18  295
父元素 296
属性 296
41.1.19  296
的父元素 296
属性 296
41.1.20 <expression-handler> 297
<expression-handler>的父元素 297
属性 297
41.1.21 <form-login> 297
<form-login>的父元素 298
<form-login>属性 298
41.1.22  299
的父元素 300
属性 300
41.1.23 元素 300
属性 300
41.1.24  300
的父元素 300
属性 301
41.1.25  302
的父元素 302
属性 302
41.1.26  302
父元素 302
属性 303
41.1.27  303
的父元素 303
属性 303
的子元素 305
41.1.28  305
的父元素 305
属性 305
的子元素 305
41.1.29  306
的父元素 306
属性 306
41.1.30  306
的父元素 306
的子元素 307
41.1.31  307
的父元素 307
属性 307
41.1.32  307
的父元素 307
属性 307
41.1.33 元素 309
的父元素 309
属性 309
41.1.34  309
的父元素 309
属性 309
的子元素 310
41.1.35  311
的父元素 311
属性 311
41.1.36  312
的父元素 312
属性 312
41.1.37  313
属性 313
的子元素 313
41.1.38  313
的父元素 313
属性 313
41.1.39  314
属性 314
的子元素 314
41.2 WebSocket安全 314
41.2.1  315
属性 315
的子元素 316
41.2.2  316
的父元素 316
属性 316
41.3认证服务 317
41.3.1  317
属性 317
的子元素 317
41.3.2  318
的父元素 318
属性 318
的子元素 318
41.3.3  319
属性 319
41.3.4  320
的父元素 320
属性 320
的子元素 320
41.3.5  320
的父元素 321
属性 321
41.3.6  321
属性 321
的子元素 321
41.3.7  321
的父元素 322
属性 322
41.4方法安全 322
41.4.1  322
属性 322
的子元素 324
41.4.2  324
的父元素 324
属性 324
41.4.3  324
的父元素 325
41.4.4  325
的父元素 325
属性 325
41.4.5  325
的父元素 325
属性 325
41.4.6  326
的父元素 326
属性 326
41.4.7使用安全方法 326
父节点 326
属性 326
41.4.8  326
属性 327
的子元素 327
41.4.9  327
属性 327
的子元素 327
41.4.10  327
父元素 328
属性 328
41.5 LDAP名称空间选项 328
41.5.1使用。定义LDAP服务器 328
属性 329
41.5.2  329
的父元素 329
属性 329
的子元素 331
41.5.3  331
的父元素 331
属性 332
的子元素 332
41.5.4  332
属性 332
42.春季安全依赖 333
42.1 spring-security-core 334
42.2 spring-security-remoting 334
42.3 spring-security-web 335
42.4 spring-security-ldap 335
42.5 spring-security-config 336
42.6 spring-security-acl 336
42.7 spring-security-cas 337
42.8 spring-security-openid 337
42.9 spring-security-taglibs 338
43.代理服务器配置 338
44. Spring Security FAQ 339
44.1一般问题 339
44.1.1 Spring Security是否会处理我所有的应用程序安全要求? 339
44.1.2为什么不使用web.xml安全? 339
44.1.3需要哪些JavaSpring Framework版本? 341
44.1.4我是Spring Security的新手,我需要构建一个支持通过HTTPS进行CAS单点登录的应用程序,同时允许对某些URL进行本地基本身份验证,并对多个后端用户信息源(LDAP和JDBC)进行身份验证。我已经复制了一些我发现的配置文件,但不起作用。什么可能是错的? 341
44.2常见问题 342
44.2.1当我尝试登录时,我收到一条错误消息,指出“Bad Credentials”。怎么了? 343
44.2.2当我尝试登录时,我的应用程序进入“无限循环”,发生了什么事? 344
44.2.3我收到一条异常消息“访问被拒绝(用户是匿名的)”。怎么了? 344
44.2.4即使在我退出应用程序之后,为什么还能看到安全的页面? 345
44.2.5我得到一个异常,消息“在SecurityContext中没有找到认证对象”。怎么了? 345
44.2.6我无法使LDAP认证正常工作。我的配置有什么问题? 345
44.2.7会话管理 346
44.2.8我使用Spring Security的并发会话控制来防止用户一次登录多次。登录后打开另一个浏览器窗口时,不会阻止我再次登录。为什么我可以多次登录? 347
44.2.9为什么在通过Spring Security进行身份验证时会话ID发生了变化? 347
44.2.10我正在使用Tomcat(或其他一些servlet容器),并为我的登录页面启用了HTTPS,之后切换回HTTP。这是行不通的 - 我只是在认证之后回到登录页面。 347
44.2.11我没有在HTTP和HTTPS之间切换,但是我的会话仍然丢失 348
44.2.12我试图使用并发会话控制支持,但是不会让我重新登录,即使我确定我已经注销并且没有超出允许的会话。 348
44.2.13 Spring Security正在创建一个会话,即使我已经配置了它,通过设置create-session属性为永远不会。 348
44.2.14执行POST时,我得到了一个403 Forbidden 349
44.2.15我正在使用RequestDispatcher将请求转发到另一个URL,但是我的安全限制没有被应用。 349
44.2.16我已经将Spring Security的元素添加到我的应用程序上下文中,但是如果将安全注释添加到我的Spring MVC控制器bean(Struts操作等)中,那么它们似乎没有效果。 349
44.2.17我有一个肯定被认证的用户,但是当我在一些请求期间尝试访问SecurityContextHolder时,认证是空的。为什么我看不到用户信息? 350
44.2.18在使用URL属性时,授权JSP标记不尊重我的方法安全注释。 350
44.3 Spring安全体系结构问题 350
44.3.1我如何知道X是哪个包? 350
44.3.2名称空间元素如何映射到传统的bean配置? 351
44.3.3“ROLE_”是什么意思,为什么我的角色名字需要它? 351
44.3.4如何知道添加到我的应用程序中的哪些依赖关系与Spring Security一起使用? 352
44.3.5运行嵌入式ApacheDS LDAP服务器需要哪些依赖关系? 352
44.3.6什么是UserDetailsService,我需要一个吗? 353
44.4共同的“Howto”请求 353
44.4.1我需要登录更多的信息,而不仅仅是用户名。如何添加对额外登录字段(例如公司名称)的支持? 354
44.4.2如果只有所请求的URL的片段值不同(例如/ foo#bar和/ foo#blah),我该如何应用不同的拦截url链接? 354
44.4.3如何在UserDetailsService中访问用户的IP地址(或其他Web请求数据)? 354
44.4.4如何从UserDetailsService访问HttpSession? 355
44.4.5如何在UserDetailsService中访问用户的密码? 355
44.4.6如何动态定义应用程序中的安全URL? 355
44.4.7如何针对LDAP进行身份验证,但从数据库加载用户角色? 357
44.4.8我想修改由命名空间创建的bean的属性,但是模式中没有任何东西支持它。我可以做什么放弃命名空间的使用? 358
45.从3.x迁移到4.x 359
				
当你想要在 Spring Security 中进行自定义身份验证时,您可以实现自定义AuthenticationProvider或自定义UserDetailsService. AuthenticationProvider: 在 AuthenticationProvider 中,可以检查用户名和密码,并在其中返回Authentication自定义对象。 UserDetailsService: 在UserDetailsService您只获得用户名时,当您返回自定义 UserDeata...
之前看过很多个版本的Spring Security中获取用户信息并进行密码校验,有在相关的Filter中获取的,也有在默认的DaoAuthenticationProvider中判断Authentication类型进行判断以后直接获取的。 不过,这些方式都不太“正宗”,Spring Security有自己的一套流程。至于此流程的详细信息讲解,先不急,本篇文章来认识一下其中比较重要的一环:获取用户信息并进行密码验证,即DaoAuthenticationProvider。 Auth...
理解AuthenticationProvider1、简介1.1 在身份验证期间表示请求1.2 实现自定义身份验证逻辑1.3 应用自定义身份验证逻辑1.3.1 实现步骤1.3.2 重写AuthenticationProvider的supports()方法1.3.3 实现身份验证逻辑1.3.4 在配置类中注册AuthenticationProvider   在企业级应用程序中,你可能会发现自己处于这样一种状况:基于用户名和密码的身份验证的默认实现并不适用。另外,当涉及身份验证时,应用程序可能需要实现几
默认实现:DaoAuthenticationProvider 授权方式提供者,判断授权有效性,用户有效性,在判断用户是否有效性,它依赖于UserDetailsService实例,开发人员可以自定义UserDetailsService的实现。 additionalAuthenticationChecks方法校验密码有效性 retrieveUser方... AuthenticationProvider可以处理特定的Authentication实现。 Spring Security:身份验证令牌Authentication介绍与Debug分析 Authentication接口及其实现类如下图所示: AuthenticationProvider接口及其实现类如下图所示: public interface AuthenticationProvider { * 使用与AuthenticationMa
什么是安全框架? 解决系统安全问题的框架。如果没有安全框架,我们需要手动处理每个资源的访问控制,非常麻烦。使用安全框架,我们可以通过配置的方式实现对资源的访问限制。 ​ Spring Securityspring家族一员。是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。 Apache Shiro 是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理。
采用SpringSecurity框架,用户登录采用拦截器实现,WebSecurityConfig实现WebSecurityConfigurerAdapter接口对拦截信息进行配置,包含设置登录页和允许访问的接口,自定义登录失败、登录成功返回对象,配置自定义密码验证拦截器对用户名和密码进行校验,判断是否为空,LoginValidateAuthenticationProvider实现AuthenticationProvider接口,获取用户名和密码,调用userService中loadUserByUsername方法,查询用户是否存在,校验用户密码是否正确,并查出用户对应的角色信息,并返回SecurityUser对象,用户身份已认证。项目启动时,执行定时任务,缓存权限数据,将需要通过认证的菜单及对应的角色信息和不需要认证的菜单分别存入reids,,用户登录后访问后台接口,拦截器调用getAttributes方法,获取redis中缓存的所有需要权限认证的url和不需要权限认证的url,获取当前访问的url信息,判断是当前访问的url是否需要认证,若为公共权限,不需要认证,直接返回null,若不是,返回该url对应的角色信息。返回后鉴权决策管理器AccessDecisionManagerImpl(实现AccessDecisionManager接口)中调用decide方法,判断configAttributes(该集合存角色信息)集合如果为空,直接通过,如果不为空,判断缓存中该url对应的角色列表是否包含当前用户角色信息,不包含抛出异常,包含则该url通过。项目中包含sql文件。
Spring Security OTP插件 Spring Security OTP插件使用Spring Security向应用程序添加了一次性密码(OTP)功能。 一次性密码令牌可以用作认证的带外第二因素。 该插件支持通过电子邮件和SMS文本传输OTP令牌。 OtpGeneratingAuthenticationProvider 这包装了一个现有的AuthenticationProvider 。 身份验证请求被委派给包装的提供程序的authenticate()方法,此嵌入式提供程序返回的Authentication令牌(例如UsernamePasswordAuthenticationToken )随后被包装在PreOtpAuthenticationToken 。 该令牌包含已包装令牌的主体和详细信息,但不公开其权限。 如果嵌入式身份验证提供程序成功验证了用户身份,则OtpGene
### 回答1: Spring Security是一个基于Spring框架的安全框架,可以帮助我们实现认证和授权等安全功能。在Spring Security中,我们可以通过自定义登录页面来实现自定义登录。 具体实现步骤如下: 1. 创建一个登录页面,可以使用JSP、Thymeleaf等模板引擎来实现。 2. 在Spring Security配置中,指定自定义登录页面的URL和处理登录请求的URL。 3. 创建一个自定义的AuthenticationProvider,用于验证用户的登录信息。 4. 在自定义的AuthenticationProvider中,实现用户信息的验证逻辑,包括用户名、密码等信息的验证。 5. 在验证通过后,将用户信息封装成一个Authentication对象,并返回给Spring Security。 6. 在Spring Security中,将Authentication对象保存到SecurityContextHolder中,以便后续的授权操作。 通过以上步骤,我们就可以实现自定义登录功能。需要注意的是,在实现自定义登录时,我们需要遵循Spring Security的安全规范,确保系统的安全性和稳定性。 ### 回答2: Spring Security是一个基于Spring框架的安全框架,常用于web应用程序的安全控制。而自定义登录是Spring Security的一个很重要的功能之一,可以让用户通过更加灵活和自由的方式登录系统。下面我将详细阐述Spring Security自定义登录的相关知识点。 1.自定义登录页面 我们可以通过自定义登录页面的形式来实现登录页面视觉效果的自定义。通常情况下,我们需要在配置文件中引入一个login-page标签,然后将其指向我们自己创建的html页面。 2.自定义验证器 Spring Security默认的验证器是AuthenticationProvider,但是我们也可以自定义自己的验证器,从而可以实现对用户提交的用户名和密码的验证。自定义的验证器通常需要实现AuthenticationProvider接口,并重写authenticate方法和supports方法。 3.自定义安全配置 我们可以通过自定义安全配置来强化系统的安全性。自定义安全配置通常需要继承WebSecurityConfigurerAdapter,并重写configure方法,从而可以实现自定义的安全配置。我们可以在这里自定义授权、认证、登录、异常处理等相关内容。 4.自定义认证成功和失败处理器 系统认证成功或失败后需要做一些后续处理,我们可以通过自定义认证成功和失败处理器来实现相应的功能。自定义认证成功和失败处理器通常需要实现AuthenticationSuccessHandler和AuthenticationFailureHandler接口。 5.自定义记住我功能 记住我功能可以实现用户重新登录时,不需要输入用户名和密码等信息。我们可以通过配置remember-me元素实现此功能。而实现自定义的记住我功能通常需要实现RememberMeServices接口,并在remember-me元素中使用custom-service-ref配置项指定实现类。 在实际的开发过程中,Spring Security自定义登录是非常常见的需求。只有通过灵活的自定义,我们才能够让系统更好地适应不同的业务需求。以上便是我对Spring Security自定义登录的详细阐述。 ### 回答3: Spring Security 是一款广泛被使用的安全框架,也是 Spring 框架的一部分,十分方便地实现了众多的安全机制。在默认配置下,Spring Security 提供了许多登录验证的实现,例如表单登录和基本认证,但仍有许多场景需要开发人员进行自定义实现。本文将着重介绍如何进行 Spring Security 自定义登录的实现。 一、配置类 首先,需要在配置类中进行一些 Bean 的配置,例如 UserDetailsService 和 PasswordEncoder,这些都是在认证过程中必要的配置项。 @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 二、自定义登录页 在默认配置下,Spring Security 提供的登录页十分简陋,我们需要自定义一个更为合适的登录界面。实现方式有很多,通常可使用 Thymeleaf 模板引擎来渲染登录页。 @Configuration public class MvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); 三、认证过程 自定义认证过程的实现,通常需要扩展 AbstractAuthenticationProcessingFilter 这个过滤器。我们需要为其提供一个 AuthenticationManager,以此来进行认证流程的管理。 public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public CustomAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (!request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); BufferedReader br = request.getReader(); String line; String requestBody = ""; while ((line = br.readLine()) != null) { requestBody += line; ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(requestBody); String username = jsonNode.get("username").asText(); String password = jsonNode.get("password").asText(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); return this.getAuthenticationManager().authenticate(token); 四、自定义用户信息 如果需要自定义用户信息,我们需要实现 UserDetails 接口和 UserDetailsService 接口。UserDetails 接口存储用户的基本信息,例如用户名,密码和授权信息。UserDetailsService 接口负责从持久化层读取用户信息。 @Service public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 从持久化层读取用户信息 return new User(username, "password", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); 本文简单介绍了 Spring Security 自定义登录的实现过程,需要开发人员在配置类,自定义登录页,认证过程以及自定义用户信息上下功夫。自定义登录能够解决默认实现无法满足的需求,提高系统的安全性。