前后端分离 spring security实现多认证功能
前后端分离 spring security实现多认证功能
spring security简说
spring security大体上是由一堆Filter(所以才能在spring mvc前拦截请求)实现的,Filter有几个,登出Filter(LogoutFilter),用户名密码验证Filter(UsernamePasswordAuthenticationFilter)之类的,Filter再交由其他组件完成细分的功能,例如最常用的UsernamePasswordAuthenticationFilter会持有一个AuthenticationManager引用,AuthenticationManager顾名思义,验证管理器,负责验证的,但AuthenticationManager本身并不做具体的验证工作,AuthenticationManager持有一个AuthenticationProvider集合,AuthenticationProvider才是做验证工作的组件,AuthenticationManager和AuthenticationProvider的工作机制可以大概看一下这两个的java doc,然后成功失败都有相对应该Handler 。大体的spring security的验证工作流程就是这样了。
推介案例
关于spring security实现多认证功能网上有大量的案例
推介一个比较友好的案例:点这儿!!!
实现方式
- 未定义多个Filter来去监听各url,因为项目本身就需要多个接口调用在接口内部模仿Filter的调用
// 该方法会去调用UserDetailsService.loadUserByUsername
authentication = authenticationManager .authenticate(new UsernamePasswordAuthenticationToken(username, password));
- 实现AuthenticationProvider接口去实现多个认证模块
public class WeChatAuthenticationProvider implements AuthenticationProvider {
@Autowired
@Qualifier(value = "WeChatUserDetailsServiceImpl")
private UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//authentication 其实就是下面定义的 xxxxToke
String code = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
//通过code获取对应的微信open等参数
//调用逻辑
return new WeChatAuthenticationToken(userDetailsService.loadUserByUsername(code);
}
@Override
public boolean supports(Class<?> aClass) {
/**
* providerManager会遍历所有
* securityconfig中注册的provider集合
* 根据此方法返回true或false来决定由哪个provider
* 去校验请求过来的authentication
*/
return (WeChatAuthenticationToken.class.isAssignableFrom(aClass));
}
}
- 编写对应的Token继承AbstractAuthenticationToken方法,可以参考UsernamePasswordAbstractAuthenticationToken实现,下图为自己定义的微信认证
public class WeChatAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 520L;
private final Object principal;
private Object credentials;
public WeChatAuthenticationToken(Object principal) {
super((Collection)null);
this.principal = principal;
this.setAuthenticated(false);
}
public WeChatAuthenticationToken(Object principal, Object credentials) {
super((Collection)null);
this.principal = principal;
this.credentials = credentials;
this.setAuthenticated(false);
}
public WeChatAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true);
}
public Object getCredentials() {
return this.credentials;
}
public Object getPrincipal() {
return this.principal;
}
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
} else {
super.setAuthenticated(false);
}
}
public void eraseCredentials() {
super.eraseCredentials();
this.credentials = null;
}
}
- 实现接口UserDetailsService 并重写对应的loadUserByUsername方法,去实现羡慕的逻辑,一般这儿我习惯写一些链接数据库的操作,而在重写的AbstractAuthenticationToken 类上就写一些参数的基本验证
public class WeChatUserDetailsServiceImpl implements UserDetailsService {
@Autowired
@Qualifier(value = "UserDetailsServiceImpl")
private UserDetailsServiceImpl userDetailsService;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
System.out.println("我进来了!!!!!" + s);
//验证参数
// userDetailsService.commonCheckData();
//返回结果集
// return userDetailsService.createLoginUser();
return null;
}
}
最后只需要在WebSecurityConfigurerAdapter的身份认证接口上把我们重写的provider方法添加上即可
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
//替换默认认证用户接口类,并声明解码方式为BCryptPasswordEncoder
//auth.userDetailsService方法把默认控制器进行替换
//会被DaoAuthenticationProvider进行调用
//.passwordEncoder(bCryptPasswordEncoder())替换默认的解密类
// auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
//账号密码登录
auth.authenticationProvider(WeChatAuthenticationProvider());
//微信登录
auth.authenticationProvider(UsernamePasswordAuthenticationProvider());
}
注意是AuthenticationManagerBuilder参数的configure方法!!!!!
如果需要多认证就多实现几个provider和token就可以了依葫芦画瓢的事情。
其实本质上spring security并不是很难,需要理解他的调用方式然后一步一步的实现,而且他自身已经有实现类给你参考了实在写不出来你就模仿他提供的类就好了比如UsernamePasswordAbstractAuthenticationToken, DaoAuthenticationProvider,UsernamePasswordAuthenticationFilter等等
上一篇: SBT 工程部署记录
下一篇: VueCli3打包后Vant样式丢失
推荐阅读
-
Java开发之spring security实现基于MongoDB的认证功能
-
Spring Boot + Vue前后端分离(三)实现登录功能
-
搭建spring-boot+vue前后端分离框架并实现登录功能
-
jwt,spring security ,feign,zuul,eureka 前后端分离 整合 实现 简单 权限管理系统 与 用户认证的实现
-
Springboot+Spring Security实现前后端分离登录认证及权限控制的示例代码
-
Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Vue前后端分离模式下无感知刷新实现JWT续期
-
Spring Security登录认证【前后端分离】
-
前后端分离 spring security实现多认证功能
-
spring boot+spring security+jwt+vue整合前后端分离token权限认证项目详细过程代码 含AES加密
-
Spring Security 简单教程以及实现完全前后端分离