详解Spring Security的Web应用和指纹登录实践

前言

Java 开发人员在解决 Web 应用安全相关的问题时,通常会采用两个非常流行的安全框架,Shiro 和 Spring Security。Shiro 配置简单,上手快,满足一般应用的安全需求,但是功能相对单一。Spring Security 安全粒度细,与 Spring Framework 无缝集成,满足绝大多数企业级应用的安全需求,但是配置复杂,学习曲线陡峭。

Spring Security 相对 Shiro 功能强大,并且 Spring Framework,Spring Boot,Spring Cloud 对 Spring Security 的支持更加友好 (毕竟是 "亲儿子")。本文将介绍 Spring Security 的架构设计、核心组件,在 Web 应用中的开发方式,最后以一个指纹登录的实例收尾。

Spring Security 核心设计

Spring Security 有五个核心组件:SecurityContext、SecurityContextHolder、Authentication、Userdetails 和 AuthenticationManager。下面分别介绍一下各个组件。

SecurityContext

SecurityContext 即安全上下文,关联当前用户的安全信息。用户通过 Spring Security 的校验之后,SecurityContext 会存储验证信息,下文提到的 Authentication 对象包含当前用户的身份信息。SecurityContext 的接口签名如清单 1 所示:

清单 1. SecurityContext 的接口签名

public interface SecurityContext extends Serializable {
    Authentication getAuthentication();
    void setAuthentication(Authentication authentication);
}

SecurityContext 存储在 SecurityContextHolder 中。

SecurityContextHolder
SecurityContextHolder 存储 SecurityContext 对象。SecurityContextHolder 是一个存储代理,有三种存储模式分别是:

  • MODE_THREADLOCAL:SecurityContext 存储在线程中。
  • MODE_INHERITABLETHREADLOCAL:SecurityContext 存储在线程中,但子线程可以获取到父线程中的 SecurityContext。
  • MODE_GLOBAL:SecurityContext 在所有线程中都相同。

SecurityContextHolder 默认使用 MODE_THREADLOCAL 模式,SecurityContext 存储在当前线程中。调用 SecurityContextHolder 时不需要显示的参数传递,在当前线程中可以直接获取到 SecurityContextHolder 对象。但是对于很多 C 端的应用(音乐播放器,游戏等等),用户登录完毕,在软件的整个生命周期中只有当前登录用户,面对这种情况 SecurityContextHolder 更适合采用 MODE_GLOBAL 模式,SecurityContext 相当于存储在应用的进程中,SecurityContext 在所有线程中都相同。

Authentication

Authentication 即验证,表明当前用户是谁。什么是验证,比如一组用户名和密码就是验证,当然错误的用户名和密码也是验证,只不过 Spring Security 会校验失败。Authentication 接口签名如清单 2 所示:

清单 2. Authentication 的接口签名

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean isAuthenticated);
}

Authentication 是一个接口,实现类都会定义 authorities,credentials,details,principal,authenticated 等字段,具体含义如下:

  • getAuthorities: 获取用户权限,一般情况下获取到的是用户的角色信息。
  • getCredentials: 获取证明用户认证的信息,通常情况下获取到的是密码等信息。
  • getDetails: 获取用户的额外信息,比如 IP 地址、经纬度等。
  • getPrincipal: 获取用户身份信息,在未认证的情况下获取到的是用户名,在已认证的情况下获取到的是 UserDetails (暂时理解为,当前应用用户对象的扩展)。
  • isAuthenticated: 获取当前 Authentication 是否已认证。
  • setAuthenticated: 设置当前 Authentication 是否已认证。

在验证前,principal 填充的是用户名,credentials 填充的是密码,detail 填充的是用户的 IP 或者经纬度之类的信息。通过验证后,Spring Security 对 Authentication 重新注入,principal 填充用户信息(包含用户名、年龄等), authorities 会填充用户的角色信息,authenticated 会被设置为 true。重新注入的 Authentication 会被填充到 SecurityContext 中。

UserDetails

UserDetails 提供 Spring Security 需要的用户核心信息。UserDetails 的接口签名如清单 3 所示:

清单 3. UserDetails 的接口签名

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}

UserDetails 用 isAccountNonExpired, isAccountNonLocked,isCredentialsNonExpired,isEnabled 表示用户的状态(与下文中提到的 DisabledException,LockedException,BadCredentialsException 相对应),具体含义如下:

  • getAuthorites:获取用户权限,本质上是用户的角色信息。
  • getPassword: 获取密码。
  • getUserName: 获取用户名。
  • isAccountNonExpired: 账户是否过期。
  • isAccountNonLocked: 账户是否被锁定。
  • isCredentialsNonExpired: 密码是否过期。
  • isEnabled: 账户是否可用。

UserDetails 也是一个接口,实现类都会继承当前应用的用户信息类,并实现 UserDetails 的接口。假设应用的用户信息类是 User,自定义的 CustomUserdetails 继承 User 类并实现 UserDetails 接口。

AuthenticationManager

AuthenticationManager 负责校验 Authentication 对象。在 AuthenticationManager 的 authenticate 函数中,开发人员实现对 Authentication 的校验逻辑。如果 authenticate 函数校验通过,正常返回一个重新注入的 Authentication 对象;校验失败,则抛出 AuthenticationException 异常。authenticate 函数签名如清单 4 所示:

清单 4. authenticate 函数签名

Authentication authenticate(Authentication authentication)throws AuthenticationException;

AuthenticationManager 可以将异常抛出的更加明确:

  • 当用户不可用时抛出 DisabledException。
  • 当用户被锁定时抛出 LockedException。
  • 当用户密码错误时抛出 BadCredentialsException。

重新注入的 Authentication 会包含当前用户的详细信息,并且被填充到 SecurityContext 中,这样 Spring Security 的验证流程就完成了,Spring Security 可以识别到 "你是谁"。

基本校验流程示例

下面采用 Spring Security 的核心组件写一个最基本的用户名密码校验示例,如清单 5 所示:

清单 5. Spring Security 核心组件伪代码

AuthenticationManager amanager = new CustomAuthenticationManager();
Authentication namePwd = new CustomAuthentication(“name”, “password”);
try {
    Authentication result = amanager.authenticate(namePwd);
    SecurityContextHolder.getContext.setAuthentication(result);
} catch(AuthenticationException e) {
    // TODO 验证失败
}

Spring Security 的核心组件易于理解,其基本校验流程是: 验证信息传递过来,验证通过,将验证信息存储到 SecurityContext 中;验证失败,做出相应的处理。

Spring Security 在 Web 中的设计

Spring Security 的一个常见应用场景就是 Web。下面讨论 Spring Security 在 Web 中的使用方式。

Spring Security 最简登录实例

Spring Security 在 Web 中的使用相对要复杂一点,会涉及到很多组件。现在给出自定义登录的伪代码,如清单 6 所示。您可以点击这里,查看完整的代码。

清单 6. Web 登录伪代码

@Controller
public class UserController { 

    @PostMapping(“/login”)
    public void login(String name, String password){
       matchNameAndPassword(name, password);
       User user = getUser(name);
       Authentication auth = new CustomAuthentication(user, password);
       auth.setAuthenticated(true);
       SecurityContextHolder.getContext.setAuthentication(auth);
    }
}

观察代码会发现,如果用 Spring Security 来集成已存在的登录逻辑,真正和 Spring Security 关联的代码只有短短 3 行。验证逻辑可以不经过 AuthenticationManager,真正需要做的就是把经过验证的用户信息注入到 Authentication 中,并将 Authentication 填充到 SecurityContext 中。在实际情况中,登录逻辑的确可以这样写,尤其是已经存在登录逻辑的时候,通常会这样写。这样写虽然方便,但是不符合 Spring Security 在 Web 中的架构设计。

下面视频中会介绍已存在的项目如何与 Spring Security 进行集成,要求对已存在的登录验证逻辑不变,但可以使用 Spring Security 的优秀特性和功能。

视频地址:https://mediacenter.ibm.com/media/0_qvbohipj

项目地址:https://github.com/springAppl/yuchigong

Spring Security 在 Web 中的核心组件

下面介绍在 Web 环境中 Spring Security 的核心组件。

FilterChainProxy

FilterChaniProxy 是 FilterChain 代理。FilterChain 维护了一个 Filter 队列,这些 Filter 为 Spring Security 提供了强大的功能。一个很常见的问题是:Spring Security 在 Web 中的入口是哪里?答案是 Filter。Spring Security 在 Filter 中创建 Authentication 对象,并调用 AuthenticationManager 进行校验。Spring Security 选择 Filter,而没有采用上文中 Controller 的方式有以下优点。Spring Security 依赖 J2EE 标准,无需依赖特定的 MVC 框架。另一方面 Spring MVC 通过 Servlet 做请求转发,如果 Spring Security 采用 Servlet,那么 Spring Security 和 Spring MVC 的集成会存在问题。FilterChain 维护了很多 Filter,每个 Filter 都有自己的功能,因此在 Spring Security 中添加新功能时,推荐通过 Filter 的方式来实现。

ProviderManager

ProviderManager 是 AuthenticationManager 的实现类。ProviderManager 并没有实现对 Authentication 的校验功能,而是采用代理模式将校验功能交给 AuthenticationProvider 去实现。这样设计是因为在 Web 环境中可能会支持多种不同的验证方式,比如用户名密码登录、短信登录、指纹登录等等,如果每种验证方式的代码都写在 ProviderManager 中,想想都是灾难。因此为每种验证方式提供对应的 AuthenticationProvider,ProviderManager 将验证任务代理给对应的 AuthenticationProvider,这是一种不错的解决方案。在 ProviderManager 中可以找到以下代码,如清单 7 所示:

清单 7. ProviderManager 代码片段

private List<AuthenticationProvider> providers;
public Authentication authenticate(Authentication authentication)
           throws AuthenticationException {
    ......
    for (AuthenticationProvider provider : getProviders()) {
       if (!provider.supports(toTest)) {
           continue;
       }
       try {
           result = provider.authenticate(authentication);
           if (result != null) {
               copyDetails(authentication, result);
               break;
           }
       }
    }
}

ProviderManager 维护了一个 AuthenticationProvider 队列。当 Authentication 传递进来时,ProviderManager 通过 supports 函数查找支持校验的 AuthenticationProvider。如果没有找到支持的 AuthenticationProvider 将抛出 ProviderNotFoundException 异常。

AuthenticationProvider

AuthenticationProvider 是在 Web 环境中真正对 Authentication 进行校验的组件。其接口签名如清单 8 所示:

清单 8. AuthenticationProvider 的接口签名

public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication)
           throws AuthenticationException;
    boolean supports(Class<?> authentication);
}

其中,authenticate 函数用于校验 Authentication 对象;supports 函数用于判断 provider 是否支持校验 Authentication 对象。

当应用添加新的验证方式时,验证逻辑需要写在对应 AuthenticationProvider 中的 authenticate 函数中。验证通过返回一个重新注入的 Authentication,验证失败抛出 AuthenticationException 异常。

Spring Security 在 Web 中的认证示例

下面的视频中会介绍采用 Spring Security 提供的 UsernamePasswordAuthenticationFilter 实现登录验证。

视频地址:https://mediacenter.ibm.com/media/0_7vq75cue

项目地址:https://github.com/springAppl/rachel

下面以用户名密码登录为例来梳理 Spring Security 在 Web 中的认证流程。上文提到 Spring Security 是以 Filter 来作为校验的入口点。在用户名密码登录中对应的 Filter 是 UsernamePasswordAuthenticationFilter。attemptAuthentication 函数会执行调用校验的逻辑。在 attemptAuthentication 函数中,可以找到以下代码,如清单 9 所示:

清单 9. attemptAuthentication 函数代码片段

public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse
response) throws AuthenticationException {
    ......
    UsernamePasswordAuthenticationToken authRequest = new
UsernamePasswordAuthenticationToken(username, password);
    setDetails(request, authRequest);
    return this.getAuthenticationManager().authenticate(authRequest);
}

attemptAuthentication 函数会调用 AuthenticationManager 执行校验逻辑,并获取到重新注入后的 Authentication。在 UsernamePasswordAuthenticationFilter 父类 AbstractAuthenticationProcessingFilter 的 successfulAuthentication 函数中发现以下代码,如清单 10 所示:

清单 10. successAuthentication 函数

protected void successfulAuthentication(HttpServletRequest request,
           HttpServletResponse response, FilterChain chain, Authentication
authResult)throws IOException, ServletException {
    ......     SecurityContextHolder.getContext().setAuthentication(authResult);
    ......
}

successfulAuthentication 函数会把重新注入的 Authentication 填充到 SecurityContext 中,完成验证。

在 Web 中,AuthenticationManager 的实现类 ProviderManager 并没有实现校验逻辑,而是代理给 AuthenticationProvider, 在用户名密码登录中就是 DaoAuthenticationProvider。DaoAuthenticationProvider 主要完成 3 个功能:获取 UserDetails、校验密码、重新注入 Authentication。在 authenticate 函数中发现以下代码,如清单 11 所示:

清单 11. DaoAuthenticationProvider.authenticate 函数签名

public Authentication authenticate(Authentication authentication)
           throws AuthenticationException {
    ......
    // 获取 UserDetails
    UserDetails user = this.userCache.getUserFromCache(username);
    if (user == null) {
       cacheWasUsed = false;
       try {
           user = retrieveUser(username,
    (UsernamePasswordAuthenticationToken) authentication);
       }
       ......
    }
    ......
    try {
       ......
       //校验密码
       additionalAuthenticationChecks(
           user,
       (UsernamePasswordAuthenticationToken) authentication
       );
    }
    ......
    // 从新注入 Authentication
    return createSuccessAuthentication(
           principalToReturn,
           authentication,
           user
        );
}

首先从 userCache 缓存中查找 UserDetails, 如果缓存中没有获取到,调用 retrieveUser 函数获取 UserDetails。retrieveUser 函数签名如清单 12 所示:

清单 12. retrieveUser 函数签名

protected final UserDetails retrieveUser(String username,
    UsernamePasswordAuthenticationToken authentication)
           throws AuthenticationException {
    UserDetails loadedUser;
    try {
        loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    }
    ......
    return loadedUser;
}

retrieveUser 函数调用 UserDetailsService 获取 UserDetails 对象。UserDetailsService 接口签名如清单 13 所示:

清单 13. UserDetailsService 接口签名

public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

UserDetailsService 非常简单,只有一个 loadUserByUserName 函数,函数参数虽然名为 username,但只要是用户的唯一标识符即可。下面是基于数据库存储的简单示例, 如清单 14 所示:

清单 14. CustomUserDetailsService 类签名

public class CustomUserDetailsService implements UserDetailsService {

  @Autowired
  private UserDao userDao;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
    User user = userDao.findByName(username);
    if(Objects.isNull(user)) {
      throw new UsernameNotFoundException();
    }
    UserDetails details = new CustomUserDetails(user);
    return details;
  }
}

调用 UserDao 获取 User 对象,将 User 对象包装成 UserDetails 对象。如果没有找到 User 对象,需要抛出 UsernameNotFoundException 异常。

DaoAuthenticationProvider 密码校验调用 additionalAuthenticationChecks 函数,具体通过 PasswordEncoder 比对用户输入的密码和存储在应用中的密码是否相等,如果不相等,抛出 BadCredentialsException 异常。

DaoAuthenticationProvider 对 Authentication 对象的重新注入通过调用 createSuccessAuthentication 函数, 如清单 15 所示:

清单 15. createSuccessAuthentication 函数签名

protected Authentication createSuccessAuthentication(Object principal,
           Authentication authentication, UserDetails user) {
    UsernamePasswordAuthenticationToken result = new
    UsernamePasswordAuthenticationToken(
        principal,
        authentication.getCredentials(),
        authoritiesMapper.mapAuthorities(user.getAuthorities())
    );
    result.setDetails(authentication.getDetails());
    return result;
}

以上就是 Spring Security 在 Web 环境中对于用户名密码校验的整个流程,简言之:

  1. UsernamePasswordAuthenticationFilter 接受用户名密码登录请求,将 Authentication 传递给 ProviderManager 进行校验。
  2. ProviderManager 将校验任务代理给 DaoAuthenticationProvider。
  3. DaoAuthenticationProvider 对 Authentication 的用户名和密码进行校验,校验通过后返回重新注入的 Authentication 对象。
  4. UsernamePasswordAuthenticationFilter 将重新注入的 Authentication 对象填充到 SecurityContext 中。

指纹登录实践

指纹登录和用户名密码登录区别很小,只是将密码换成了指纹特征值。下面采用 Spring Security 推荐写法 Filter-AuthenticationProvider 的形式来定义相关组件以实现指纹登录。完整的项目地址:https://github.com/springAppl/rachel

FingerPrintToken

FingerPrintToken 增加 name 和 fingerPrint 字段,分别代表用户名和指纹特征值,如清单 16 所示:

清单 16. FingerPrintToken 函数签名

public class FingerPrintToken implements Authentication {
    private String name;
    private String fingerPrint;
    ......
}

FingerPrintFilter

FingerPrintFilter 处理指纹登录请求,调用 AuthenticationManager 进行验证,验证通过后调用 SecurityContextHolder 将重新注入的 Authentication 填充到 SecurityContext 中,如清单 17 所示:

清单 17. doFilter 函数签名

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
    if (Objects.equals(httpServletRequest.getRequestURI(), "/api/finger-print")) {
        // 调用 AuthenticationManager, 并填充 SecurityContext
    }
}

FingerPrintProvider

FingerPrintProvider 负责处理 FingerPrintToken,需要在 supports 函数中支持处理 FingerPrintToken。authenticate 函数负责 UserDetails 获取,指纹校验,FingerPrintToken 的重新注入。

FingerPrintUserDetails

FingerPrintUserDetails 继承 User 并实现 UserDetails 的方法,应用的用户信息可以加载到 Spring Security 中使用。

FingerPrintUserDetailsService

FingerPrintUserDetailsService 获取 FingerUserDetails。通过 UserDao 查找到 User,并将 User 转换为 Spring Security 可识别 UserDetails。

SecurityConfig

SecurityConfig 继承 WebSecurityConfigurerAdapter,需要定义 Spring Security 配置类。Spring Security 的配置不是本文的重点,配置时只需要注意以下几点:

  1. 将 FingerPrintFilter、FingerPrintProvider 添加进去。
  2. 将 FingerPrintFilter 的执行顺序放置在 SecurityContextPersistenceFilter 之后即可。Spring Security 维护了一个 Filter 的 list,因此每个 Filter 是有顺序的。
  3. 将 "/api/test" 请求设置为用户验证成功后才允许方问。

配置代码在 configure 函数中,如清单 18 所示:

清单 18. configure 函数

protected void configure(HttpSecurity http) throws Exception {
    http
       .userDetailsService(userDetailsService())
       .addFilterAfter(fingerPrintFilter(), SecurityContextPersistenceFilter.class)
       .authenticationProvider(fingerPrintProvider())
       .authorizeRequests()
       .mvcMatchers(HttpMethod.GET, "/api/test").authenticated()
}

总结

在 Web 时代,用户和应用的耦合度越来越高,应用中存储了大量用户的私密信息。随着各种用户信息泄露事件的爆发,安全成为了 Web 应用重要的一个环。Spring Security 由于其强大的功能和 Spring Framework 的高度集成,赢得了开发人员的青睐。本文对 Spring Security 的架构设计与核心组件进行了深入浅出的介绍,分析了 Spring Security 在 Web 应用的集成方式,并展示了一个指纹登录的实例。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring Boot整合Spring Security简单实现登入登出从零搭建教程

    前言 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 本文主要给大家介绍了关于Spring Boot整合S

  • SpringSecurity学习之自定义过滤器的实现代码

    我们系统中的认证场景通常比较复杂,比如说用户被锁定无法登录,限制登录IP等.而SpringSecuriy最基本的是基于用户与密码的形式进行认证,由此可知它的一套验证规范根本无法满足业务需要,因此扩展势在必行.那么我们可以考虑自己定义filter添加至SpringSecurity的过滤器栈当中,来实现我们自己的验证需要. 本例中,基于前篇的数据库的Student表来模拟一个简单的例子:当Student的jointime在当天之后,那么才允许登录 一.创建自己定义的Filter 我们先在web包下创

  • Spring Security Oauth2.0 实现短信验证码登录示例

    本文介绍了Spring Security Oauth2.0 实现短信验证码登录示例,分享给大家,具体如下: 定义手机号登录令牌 /** * @author lengleng * @date 2018/1/9 * 手机号登录令牌 */ public class MobileAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecur

  • SpringBoot + SpringSecurity 短信验证码登录功能实现

    实现原理 在之前的文章中,我们介绍了普通的帐号密码登录的方式: SpringBoot + Spring Security 基本使用及个性化登录配置. 但是现在还有一种常见的方式,就是直接通过手机短信验证码登录,这里就需要自己来做一些额外的工作了. 对SpringSecurity认证流程详解有一定了解的都知道,在帐号密码认证的过程中,涉及到了以下几个类:UsernamePasswordAuthenticationFilter(用于请求参数获取),UsernamePasswordAuthentica

  • Spring security实现登陆和权限角色控制

     随笔简介 1.spring版本:4.3.2.RELEASE+spring security 版本:4.1.2.RELEASE(其它不做说明) 2.所展示内容全部用注解配置 3.springmvc已经配置好,不作说明 4.会涉及到springmvc,spel,el的东西,不熟悉的同学可以先去看一下这方面内容,特别是springmvc 首先想一下,登陆需要什么,最简单的情况下,用户名,密码,然后比对数据库,如果吻合就跳转到个人页面,否则回到登陆页面,并且提示用户名密码错误.这个过程中应该还带有权限

  • Spring security实现权限管理示例

    Spring security实现权限管理示例,具体如下: 1.配置文件 1.POM.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.o

  • Java中SpringSecurity密码错误5次锁定用户的实现方法

    Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 下面看下实例代码: 第

  • spring security 5.x实现兼容多种密码的加密方式

    前言 本文主要给大家介绍了关于spring security 5.x实现兼容多种密码的加密方式,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 1.spring security PasswordEncoder spring security 5不需要配置密码的加密方式,而是用户密码加前缀的方式表明加密方式,如: {MD5}88e2d8cd1e92fd5544c8621508cd706b代表使用的是MD5加密方式: {bcrypt}$2a$10$eZeGvVV2ZXr/vgiV

  • 详解Spring Security的Web应用和指纹登录实践

    前言 Java 开发人员在解决 Web 应用安全相关的问题时,通常会采用两个非常流行的安全框架,Shiro 和 Spring Security.Shiro 配置简单,上手快,满足一般应用的安全需求,但是功能相对单一.Spring Security 安全粒度细,与 Spring Framework 无缝集成,满足绝大多数企业级应用的安全需求,但是配置复杂,学习曲线陡峭. Spring Security 相对 Shiro 功能强大,并且 Spring Framework,Spring Boot,Sp

  • 详解spring security四种实现方式

    spring security实现方式大致可以分为这几种: 1.配置文件实现,只需要在配置文件中指定拦截的url所需要权限.配置userDetailsService指定用户名.密码.对应权限,就可以实现. 2.实现UserDetailsService,loadUserByUsername(String userName)方法,根据userName来实现自己的业务逻辑返回UserDetails的实现类,需要自定义User类实现UserDetails,比较重要的方法是getAuthorities()

  • 详解Spring Security中获取当前登录用户的详细信息的几种方法

    目录 在Bean中获取用户信息 在Controller中获取用户信息 通过 Interface 获取用户信息 在JSP页面中获取用户信息 在Bean中获取用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentU

  • 详解Spring Security中权限注解的使用

    目录 1. 具体用法 2. SpEL 3. @PreAuthorize 最近有个小伙伴在微信群里问 Spring Security 权限注解的问题: 很多时候事情就是这么巧,松哥最近在做的 tienchin 也是基于注解来处理权限问题的,所以既然大家有这个问题,咱们就一块来聊聊这个话题. 当然一些基础的知识我就不讲了,对于 Spring Security 基本用法尚不熟悉的小伙伴,可在公众号后台回复 ss,有原创的系列教程. 1. 具体用法 先来看看 Spring Security 权限注解的具

  • 详解Spring Security如何在权限中使用通配符

    目录 前言 1. SpEL 2. 自定义权限该如何写 3. 权限通配符 4. TienChin 项目怎么做的 前言 小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限: system:user:add system:user:delete system:user:select system:user:update … 现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符: system:user:* 这个通配符就表示拥有针对用户的

  • 详解Spring Security 中的四种权限控制方式

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权逻辑.一句话,你想怎么玩都可以! 今天松哥来和大家介绍一下 Spring Security 中四种常见的权限控制方式. 表达式控制 URL 路径权限 表达式控制方法权限 使用过滤注解 动态权限 四种方式,我们分别来看.  1.表达式控制 URL 路径权

  • 一文详解Spring Security的基本用法

    目录 1.引入依赖 2.用户名和密码在哪里设置 3.UserDetailsService接口详解 3.1JdbcDaoImpl实现类 3.2InMemoryUserDetailsManager实现类 3.3自定义实现类实现UserDetailsService接口 4.如何修改登录页面 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架, 提供了完善的认证机制和方法级的授权功能.是一款非常优秀的权限管理框架.它的核心是一组过滤器链,不同的功能经由不同的过滤器. 今天通

  • 详解spring security安全防护

    前言 xss攻击(跨站脚本攻击):攻击者在页面里插入恶意脚本代码,用户浏览该页面时,脚本代码就会执行,达到攻击者的目的.原理就是:攻击者对含有漏洞的服务器注入恶意代码,引诱用户浏览受到攻击的服务器,并打开相关页面,执行恶意代码. xss攻击方式:一.反射性攻击,脚本代码作为url参数提交给服务器,服务器解析执行后,将脚本代码返回给浏览器,最后浏览器解析执行攻击代码:二.存储性攻击,和发射性攻击的区别是,脚本代码存储在服务器,下次在请求时,不用再提交脚本代码.其中一个示例图如下所示: CSRF攻击

  • 详解Spring Security如何配置JSON登录

    spring security用了也有一段时间了,弄过异步和多数据源登录,也看过一点源码,最近弄rest,然后顺便搭oauth2,前端用json来登录,没想到spring security默认居然不能获取request中的json数据,谷歌一波后只在stackoverflow找到一个回答比较靠谱,还是得要重写filter,于是在这里填一波坑. 准备工作 基本的spring security配置就不说了,网上一堆例子,只要弄到普通的表单登录和自定义UserDetailsService就可以.因为需

  • 详解spring security 配置多个AuthenticationProvider

    前言 发现很少关于spring security的文章,基本都是入门级的,配个UserServiceDetails或者配个路由控制就完事了,而且很多还是xml配置,国内通病...so,本文里的配置都是java配置,不涉及xml配置,事实上我也不会xml配置 spring security的大体介绍 spring security本身如果只是说配置,还是很简单易懂的(我也不知道网上说spring security难,难在哪里),简单不需要特别的功能,一个WebSecurityConfigurerA

随机推荐