通过Spring Security魔幻山谷讲解获取认证机制核心原理

本文基于Springboot+Vue+Spring Security框架而写的原创学习笔记,demo代码参考《Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统》一书。

这是一个古老的传说。

在神秘的Web系统世界里,有一座名为SpringSecurity的山谷,它高耸入云,蔓延千里,鸟飞不过,兽攀不了。这座山谷只有一条逼仄的道路可通。然而,若要通过这条道路前往另一头的世界,就必须先拿到一块名为token的令牌,只有这样,道路上戍守关口的士兵才会放行。

想要获得这块token令牌,必须带着一把有用的userName钥匙和password密码,进入到山谷深处,找到藏匿宝箱的山洞(数据库),若能用钥匙打开其中一个宝箱,就证明这把userName钥匙是有用的。正常情况下,宝箱里会有一块记录各种信息的木牌,包含着钥匙名和密码,其密码只有与你所携带的密码检验一致时,才能继续往前走,得到的通行信息将会在下一个关口处做认证,进而在道路尽头处的JWT魔法屋里获得加密的token令牌。

慢着,既然山谷关口处有士兵戍守,令牌又在山谷当中,在还没有获得令牌的情况下,又怎么能进入呢?

设置关口的军官早已想到这种情况,因此,他特意设置了一条自行命名为“login”的道路,没有令牌的外来人员可从这条道路进入山谷,去寻找传说中的token令牌。这条道路仅仅只能进入到山谷,却无法通过山谷到达另一头的世界,因此,它更像是一条专门为了给外来人员获取token令牌而开辟出来的道路。

这一路上会有各种关口被士兵把守检查,只有都一一通过了,才能继续往前走,路上会遇到一位名为ProviderManager的管理员,他管理着所有信息提供者Provider......需找到一位可正确带路的信息提供者Provider,在他的引导下,前往山洞(数据库),成功获取到宝箱,拿到里面记录信息的木牌,这样方能验证所携带的username和password是否正确。若都正确,那么接下来就可将信息进行认证,并前往JWT魔法屋获取token令牌。最后携带着token返回到家乡,让族人都可穿过山谷而进入到web系统,去获取更多珍贵的资源。

这就是整个security的游戏规则原理。

那么,在游戏开始之前,我们先了解下当年戍守山谷的军官是如何设置这道权限关口的......

关口的自定义设置主要有三部分:通过钥匙username获取到宝箱;宝箱里的UserDetails通行信息设置;关口通行过往检查SecurityConfig设置。

一.宝箱里的通行信息:

/**
* 安全用户模型
*
* @author zhujiqian
* @date 2020/7/ 15:
*/
public class JwtUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private String salt;
private Collection<? extends GrantedAuthority> authorities;
JwtUserDetails(String username, String password, String salt, Collection<? extends GrantedAuthority> authorities) {
    this.username = username;
  this.password = password;
   this.salt = salt;
   this.authorities = authorities;
}
@Override
public String getUsername() {
   return username;
}
@JsonIgnore
@Override
public String getPassword() {
    return password;
}
public String getSalt() {
    return salt;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
   return authorities;
}
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
    return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
   return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
    return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
    return true;
}
  }

这里JwtUserDetails实现Spring Security 里的UserDetails类,这个类是长这样的,下面对各个字段做了注释:

 public interface UserDetails extends Serializable {
/**
*用户权限集,默认需要添加ROLE_前缀
*/
Collection<? extends GrantedAuthority> getAuthorities();
/**
*用户的加密密码,不加密会使用{noop}前缀
*/
String getPassword();
/**
*获取应用里唯一用户名
*/
String getUsername();
/**
*检查账户是否过期
*/
boolean isAccountNonExpired();
/**
*检查账户是否锁定
*/
boolean isAccountNonLocked();
/**
*检查凭证是否过期
*/
boolean isCredentialsNonExpired();
/**
*检查账户是否可用
*/
boolean isEnabled();
  }

说明:JwtUserDetails自定义实现了UserDetails类,增加username和password字段,除此之外,还可以扩展存储更多用户信息,例如,身份证,手机号,邮箱等等。其作用在于可构建成一个用户安全模型,用于装载从数据库查询出来的用户及权限信息。

二.通过钥匙username获取到宝箱方法:

/**
 * 用户登录认证信息查询
 *
 * @author zhujiqian
 * @date 2020/7/30 15:30
 */
 @Service
 public class UserDetailsServiceImpl implements UserDetailsService {
 @Resource
 private SysUserService sysUserService;
 @Override
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 SysUser user = sysUserService.findByName(username);
 if (user == null) {
  throw new UsernameNotFoundException("该用户不存在");
 }
 Set<String> permissions = sysUserService.findPermissions(user.getName());
 List<GrantedAuthority> grantedAuthorities = permissions.stream().map(AuthorityImpl::new).collect(Collectors.toList());
 return new JwtUserDetails(user.getName(), user.getPassword(), user.getSalt(), grantedAuthorities);
	  }
  }

这个自定义的UserDetailsServiceImpl类实现了Spring Security框架自带的UserDetailsService接口,这个接口只定义一个简单的loadUserByUsername方法:

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

根据loadUserByUsername方法名便能看出,这是一个可根据username用户名获取到User对象信息的方法,并返回一个UserDetails对象,即前头的“宝箱里的通行信息”,换言之,通过重写这个方法,我们能在该方法里实现用户登录认证信息的查询,并返回对应查询信息。

综合以上代码,先用开头提到的宝箱意象做一个总结,即拿着userName这把钥匙,通过loadUserByUsername这个方法指引,可进入到山洞(数据库),去寻找能打开的宝箱(在数据库里select查询userName对应数据),若能打开其中一个宝箱(即数据库里存在userName对应的数据),则获取宝箱里的通行信息(实现UserDetails的JwtUserDetails对象信息)。

三.关口通行过往检查设置

自定义的SecurityConfig配置类是SpringBoot整合Spring Security的关键灵魂所在。该配置信息会在springboot启动时进行加载。其中,authenticationManager()会创建一个可用于传token做认证的AuthenticationManager对象,而AuthenticationManagerBuilder中的auth.authenticationProvider()则会创建一个provider提供者,并将userDetailsService注入进去,该userDetailsService的子类被自定义的UserDetailsServiceImpl类继承,并重写loadUserByUsername()方法,因此,当源码里执行userDetailsService的loadUserByUsername()方法时,即会执行被重写的子类loadUserByUsername()方法。

由此可见,在做认证的过程中,只需找到注入userDetailsService的provider对象,即可执行loadUserByUsername去根据username获取数据库里信息。

那具体是在哪个provider对象?请看下面详细解析。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 @Resource
 private UserDetailsService userDetailsService;
 @Override
public void configure(AuthenticationManagerBuilder auth) {
 auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));
}
@Bean
@Override
public AuthenticationManager authenticationManager() throws Exception {
 return super.authenticationManager();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
 //使用的是JWT,禁用csrf
 httpSecurity.cors().and().csrf().disable()
//设置请求必须进行权限认证
.authorizeRequests()
//跨域预检请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
//permitAll()表示所有用户可认证
.antMatchers( "/webjars/**").permitAll()
//首页和登录页面
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
// 验证码
.antMatchers("/captcha.jpg**").permitAll()
// 其他所有请求需要身份认证
.anyRequest().authenticated();
 //退出登录处理
 httpSecurity.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
 //token验证过滤器
 httpSecurity.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
}
  }

首先,双击SecurityConfig 类里的JwtAuthenticationProvider——

进入到JWTAuthenticationProvider类内部,发现原来该类是继承了DaoAuthenticationProvider。

请注意这段话,很关键:

点击setUserDetailsService(userDetailsService)。进入到方法里面后,发现这里其实是把UserDetailsService通过set方式依赖注入到DaoAuthenticationProvider类中,换言之,我们接下来在加载完成的框架里只需通过DaoAuthenticationProvider的getUserDetailsService()方法,便可获取前面注入的userDetailsService,进而调用其子类实现的loadUserByUsername()方法。

看到这里,您须重点关注一下DaoAuthenticationProvider这个类,它将会在后面再次与我们碰面,而它是一个AuthenticationProvider。

若您还不是很明白AuthenticationProvider究竟是什么,那就暂且统一把它当做信息提供者吧,而它是ProviderManager管理员底下其中一个信息提供者Provider。

写到这里,还有一个疑问,即security框架是如何将信息提供者Provider归纳到ProviderManager管理员手下的呢?

解答这个问题,需回到SecurityConfig配置文件里,点击authenticationProvider进入到底层方法当中。

进入后,里面是具体的方法实现,大概功能就是把注入了userDetailsService的信息提供者DaoAuthenticationProvider添加到一个List集合里,然后再将集合里的所有提供者,通过构造器传入ProviderManager,命名生成一个新的提供者管理员providerManager。这里面还涵盖不少细节,感兴趣的读者可自行再扩展深入研究。

以上,就初步设置好了游戏规则。

接下来,就是主角上场了。

在所有的游戏里,都会有一个主角,而我们这个故事,自然也不例外。

此时,在一扇刻着“登录”二字的大门前,有一个小兵正在收拾他的包袱,准备跨过大门,踏上通往SpringSecurity山谷的道路。他背负着整个家族赋予的任务,需前往Security山谷,拿到token令牌,只有把它成功带回来,家族里的其他成员,才能有机会穿过这座山谷,前往另一头的神秘世界,获取到珍贵的资源。

这个小兵,便是我们这故事里的主角,我把他叫做线程,他将带着整个线程家族的希望,寻找可通往神秘系统世界的令牌。

线程把族长给予的钥匙和密码放进包袱,他回头看了一眼自己的家乡,然后挥了挥手,跨过“登录”这扇大门,勇敢地上路了。

线程来到戒备森严的security关口前,四周望了一眼,忽然发现关口旁立着一块显眼的石碑,上面刻着一些符号。他走上前一看,发现原来是当年军官设置的指令与对应的说明:

  @Override
 protected void configure(HttpSecurity httpSecurity) throws Exception {
  //使用的是JWT,禁用csrf
  httpSecurity.cors().and().csrf().disable()
 //设置请求必须进行权限认证
 .authorizeRequests()
 //跨域预检请求
 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
 //首页和登录页面
.antMatchers("/login").permitAll()
// 其他所有请求需要身份认证
.anyRequest().authenticated();
 //退出登录处理
 httpSecurity.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
 //token验证过滤器
 httpSecurity.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
}

其中,permitAll()代表所有请求都可访问,当它设置成类似“.antMatchers("/login").permitAll()”的形式时,则代表该/login路径请求无需认证便可通过,相反,代码anyRequest().authenticated()则意味着其他的所有请求都必须进行身份验证方能通过,否则,会被拒绝访问。

下面,将通过debug一步一步揭示,线程是如何闯关升级的,最后成功获取到传说中的token令牌。

线程来到关口处,不久,在戍守士兵的指引下,开始往login道路走去,前面迎接他,将是一系列的关口检查。

1.传入userName,password属性,封装成一个token对象。

进入到该对象里,可看到用户名赋值给this.principal,密码赋值给this.credentials,其中setAuthenticated(false)意味着尚未进行认证。

注意一点是,UsernamePasswordAuthenticationToken继承了AbstractAuthenticationToken,而AbstractAuthenticationToken实现Authentication,由传递关系可知,Authentication是UsernamePasswordAuthenticationToken的基类,故而UsernamePasswordAuthenticationToken是可以向上转换为Authentication,理解这一点,就能明白,为何接下来authenticationManager.authenticate(token)方法传进去的是UsernamePasswordAuthenticationToken,但在源码里,方法参数则为Authentication。

2.将username,password封装成token对象。

通过Authenticationauthentication=authenticationManager.authenticate(token)方法进行认证,里面会执行一系列认证操作,需要看懂源码,才能知道这行代码背后藏着的水月洞天,然,有一点是可以从表面上看懂的,即若成功认证通过,将会返回一个认证成功的Authentication对象,至于对象里是什么信息,请继续 往下看。

3.点击进入到AuthenticationManager里,发现该接口里只有一个方法:

Authentication authenticate(Authentication authentication)
     throws AuthenticationException;

由此可知,它的具体实现,是通过实现类来操作的,它的主要实现类有N多个,其中,在认证过程中,我们需关注的是ProviderManager这个类。

这个ProviderManager,即前面提到的Provider管理员,他管理着一堆信息提供者provider。线程此行的目的,就是先找到这个Provider管理员,再去管理员手中寻找能够匹配到的提供者provider,只有通过匹配到的提供者,才能找到获取数据库的方法loadUserByUsername。

4.ProviderManager类实际上是实现AuthenticationManager接口。

重写authenticate方法。因此,当前面代码执行authenticationManager.authenticate(token)方法时,具体实现将由其子类重写的方法操作,子类即ProviderManager。

debug进去后——

继续往下执行,通过getProviders() 可获取到内部维护在List中的AuthenticationProvider遍历进行验证,若该提供者能支持传入的token进行验证,则继续往下执行。

其中,JwtAuthAuthenticationProvider可执行本次验证,而JwtAuthAuthenticationProvider是继承DaoAuthenticationProvider后自定义的类,可以理解成,进行认证验证的Provider是前面重点提到的DaoAuthenticationProvider。

DaoAuthenticationProvider是一个具体实现类,它继承AbstractUserDetailsAuthenticationProvider抽象类。

而AbstractUserDetailsAuthenticationProvider实现了AuthenticationProvider接口。

5.在ProviderManager中,执行到result =provider.authenticate(authentication)。

其中provider是由AuthenticationProvider定义的,但AuthenticationProvider是一个接口,需由其子类具体实现。根据上面分析,可知,AbstractUserDetailsAuthenticationProvider会具体实现provider.authenticate(authentication)方法。debug进入到其authenticate方法当中,会跳转到AbstractUserDetailsAuthenticationProvider重写的authenticate()方法当中,接下来会详细介绍该authenticate()执行的代码模块:

5.1.首先,第一步,会执行this.userCache.getUserFromCache(username)获取缓存里的信息。

5.2若缓存里没有UserDetails信息,将会继续往下执行。

执行到retrieveUser方法,该方法的总体作用是:通过登录时传入的userName去数据库里做查询,若查询成功,便将数据库的User信息包装成UserDetails对象返回,当然,具体如何从数据库里获取到信息,则需要重写一个方法,即前面提到的loadUserByUsername()方法。

值得注意一点是,一般新手接触到security框架,都会有一个疑问,即我登录时传入了username,是如何获取到数据库里的用户信息?

其实,这个疑问的关键答案,就藏在这个retrieveUser()方法里。该方法名的英文解析是:“(训练成能寻回猎物的)猎犬”。我觉得这个翻译在这里很有意思,暂且可以把它当成信息提供者Provider驯养的一头猎犬,它可以帮我们的游戏主角线程在茫茫的森林里,寻找到藏匿宝箱的山洞(数据库)。

5.3 ,接下来,就让这头猎犬给我们带路吧——点击retrieveUser()。

进入到方法当中,发现,这其实是一个抽象方法,故而其具体实现将在子类中进行。

5.4进入到其子类实现的方法当中。

发现会进入前面提到AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider它也是一个AuthenticationProvider,即所谓的信息提供者之一。在DaoAuthenticationProvider类里,实现了父类的retrieveUser方法。

在猎犬的(retrieveUser)的带路下,我们最后看到 了熟悉的老朋友,关键方法loadUserByUserName()。

点进loadUserByUsername()方法里,会进入到UserDetailsService接口里,该接口只有loadUserByUsername一个方法,该方法具体在子类里实现。

这个接口被我们自定义重写了,即前面露过面的:

在DaoAuthenticationProvider类中,调用loadUserByUserName()方法时,最终会执行我们重写的loadUserByUsername()方法,该方法将会去数据库里查询username的信息,并返回一个User对象,最后SysUser对象转换成UserDetails,返回给DaoAuthenticationProvider对象里的UserDetails,跳转如下图:

5.5DaoAuthenticationProvider的retirieveUser执行完后。

会将数据库查询到的UserDetails返回给上一层,即AbstractUserDetailsAuthenticationProvider执行的retrieveUser()方法,得到的UserDetails赋值给user。

6.接下来就是各种检查。

其中,有一个检查方法需要特别关注

注:additionalAuthenticationChecks()方法的作用是检查密码是否一致的,前面已根据username去数据库里查询出user数据,接下来,就需要在该方法里,检查数据库里user的密码与登录时传入的密码是否一致了。

6.1点击additionalAuthenticationChecks()进入到方法里。

发现AbstractUserDetailsAuthenticationProvider当中的additionalAuthenticationChecks同样是一个抽象方法,没有具体实现,它与前面的retrieveUser()方法一样,具体实现都在AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider中重写了。

6.2.跳转进入子类重写的additionalAuthenticationChecks()当中。

先通过authentication.getCredentials().toString()从token对象中获取登录时输入的密码,再通过passwordEncoder.matches(presentedPassword,userDetails.getPassword())进行比较,即拿登录的密码与数据库里取出的密码做对比,执行到这一步,若两个密码一致时,即登录的username和password能与数据库里某个username和密码匹配,则可登录成功。

7.用户名与密码都验证通过后,可继续执行下一步操作。

中间还有几个检查方法,读者若感兴趣,可自行研究。最后会把user赋值给一个principalToReturn对象,然后连同authentication还有user,一块传入到createSuccessAuthentication方法当中。

8.在createSuccessAuthentication方法里,会创建一个已经认证通过的token。

点进该token对象当中,可以看到,这次的setAuthenticated设置成了true,即意味着已经认证通过。

最后,将生成一个新的token,并以Authentication对象形式返回到最开始的地方。

执行到这一步,就可以把认证通过的信息进行存储,到这里,就完成了核心的认证部分。

接下来,我们的主角线程就可以前往JWT魔法屋获取加密的token令牌,然后携带令牌返回故土,届时,其线程家族里的其他成员,都可穿过这座Spring Security山谷,前往山谷另一边的web系统世界了。

那是另外一个世界的故事,我们将在以后漫长的岁月当中,缓缓道来.....

而这个关于Spring Security山谷的故事,就暂且记到这里,若当中有不当之处,还需各位大佬指出而加以改进。

到此这篇关于通过Spring Security魔幻山谷讲解获取认证机制核心原理的文章就介绍到这了,更多相关Spring Security内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解析spring-security权限控制和校验的问题

    前言     在我们项目中经常会涉及到权限管理,特别是一些企业级后台应用中,那权限管理是必不可少的.这个时候就涉及到技术选型的问题.在我以前项目中也没用到什么权限框架,就全部到一个spring mvc拦截器中去校验权限,当然,对需求比较少,小型的项目这也不失一个好的实现(实现简单,功能单一),但是对于一些比较大的应用,权限认证,session管理要求比较高的项目,如果再使用mvc拦截器,那就得不偿失了(需要自己去实现很多的代码).     现在比较流行的权限校验框架有spring-securit

  • spring Security的自定义用户认证过程详解

    首先我需要在xml文件中声明.我要进行自定义用户的认证类,也就是我要自己从数据库中进行查询 <http pattern="/*.html" security="none"/> <http pattern="/css/**" security="none"/> <http pattern="/img/**" security="none"/> <h

  • 话说Spring Security权限管理(源码详解)

    最近项目需要用到Spring Security的权限控制,故花了点时间简单的去看了一下其权限控制相关的源码(版本为4.2). AccessDecisionManager spring security是通过AccessDecisionManager进行授权管理的,先来张官方图镇楼. AccessDecisionManager AccessDecisionManager 接口定义了如下方法: //调用AccessDecisionVoter进行投票(关键方法) void decide(Authent

  • 详解spring security四种实现方式

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

  • Spring Security 自定义短信登录认证的实现

    自定义登录filter 上篇文章我们说到,对于用户的登录,security通过定义一个filter拦截login路径来实现的,所以我们要实现自定义登录,需要自己定义一个filter,继承AbstractAuthenticationProcessingFilter,从request中提取到手机号和验证码,然后提交给AuthenticationManager: public class SmsAuthenticationFilter extends AbstractAuthenticationPro

  • 通过Spring Security魔幻山谷讲解获取认证机制核心原理

    本文基于Springboot+Vue+Spring Security框架而写的原创学习笔记,demo代码参考<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>一书. 这是一个古老的传说. 在神秘的Web系统世界里,有一座名为SpringSecurity的山谷,它高耸入云,蔓延千里,鸟飞不过,兽攀不了.这座山谷只有一条逼仄的道路可通.然而,若要通过这条道路前往另一头的世界,就必须先拿到一块名为token的令牌,只有这样,道路上戍守关口

  • Spring Boot示例分析讲解自动化装配机制核心注解

    目录 1. 自动化装配介绍 2. Spring Boot 自动化配置UML图解 3. Spring Boot 自动化配置核心注解分析 3.1 @Inherited 3.2 @SpringBootConfiguration 3.3 @EnableAutoConfiguration 3.4 @ComponentScan 3.5 @ConfigurationPropertiesScan 3.6 @AutoConfigurationImportSelector 3.7 @AutoConfiguratio

  • Java开发之spring security实现基于MongoDB的认证功能

    本文实例讲述了Java开发之spring security实现基于MongoDB的认证功能.分享给大家供大家参考,具体如下: spring security对基于数据库的认证支持仅限于JDBC,而很多项目并非使用JDBC,比如Nosql数据库很多使用的是 Mongo Java Driver,这样就无法用默认的<jdbc-user-service>进行支持认证. 如果项目不是使用JDBC,没么解决办法就是:自己定义一个认证服务. 新建一个CustomUserDetailsService类 这个类

  • SpringBoot集成Spring security JWT实现接口权限认证

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjw

  • Spring Boot超详细讲解请求处理流程机制

    目录 1. 背景 2. Spring Boot 的请求处理流程设计 3. Servlet服务模式请求流程分析 3.1 ServletWebServerApplicationContext分析 3.2 Servlet服务模式之请求流程具体分析 4. Reactive服务模式请求流程分析 4.1 ReactiveWebServerApplicationContext分析 4.2 webflux服务模式之请求流程具体分析 5. 总结 1. 背景 之前我们对Spring Boot做了研究讲解,我们知道怎

  • Spring security基于数据库中账户密码认证

    一.原理分析 前台的登录请求发送到后端后会由spring security进行拦截,即controller层由框架自己提供.这样用户名和密码的认证就需要在service层完成,所以框架需要在service层获取到我们自己的数据库账号信息. spring security 提供了一个接口 UserDetailsService 来让用户提供账号和密码,其内容如下 public interface UserDetailsService { UserDetails loadUserByUsername(

  • Spring Security如何基于Authentication获取用户信息

    Spring Security使用一个Authentication对象来描述当前用户的相关信息.SecurityContextHolder中持有的是当前用户的SecurityContext,而SecurityContext持有的是代表当前用户相关信息的Authentication的引用. 这个Authentication对象不需要我们自己去创建,在与系统交互的过程中,Spring Security会自动为我们创建相应的Authentication对象,然后赋值给当前的SecurityContex

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

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

  • Java Spring Security认证与授权及注销和权限控制篇综合解析

    Spring Security简介: Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,它可以实现强大的Web安全控制,对于安全控制,我们只需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理! 记住几个类: WebSecurityConfigurerAdapter:自定义Security策略 AuthenticationManagerBuilder:自定义认证策略

随机推荐