我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringSecurity自定义认证器的实现代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringSecurity自定义认证器的实现代码

在了解过Security的认证器后,如果想自定义登陆,只要实现AuthenticationProvider还有对应的Authentication就可以了

Authentication

首先要创建一个自定义的Authentication,Security提供了一个Authentication的子类AbstractAuthenticationToken

我们实现这个类可以了,他已经实现了Authentication的一些方法

public class NamePassAuthenticationToken extends AbstractAuthenticationToken {

    private static final long serialVersionUID = 520L;
    private final Object principal;
    private Object credentials;

//提供第一次进来的构造方法
    public NamePassAuthenticationToken(Object principal, Object credentials) {
        super((Collection)null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }

//提供填充Authentication的构造方法
    public NamePassAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    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);
        }
    }

    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
        this.credentials = null;
    }
}

这个类关键就是一个是认证的,一个没认证的的构造器

AuthenticationProvider

接着是AuthenticationProvider,需要实现他的authenticate方法

@Setter
public class NamePassAuthenticationProvider implements AuthenticationProvider {

    private CustomUserDetailsService userDetailsService;

    private PasswordEncoder passwordEncoder;

    @Override
    //具体认证逻辑
    public Authentication authenticate(Authentication authentication) {
        NamePassAuthenticationToken authenticationToken = (NamePassAuthenticationToken) authentication;
        String username = (String) authenticationToken.getPrincipal();
        String password = (String) authenticationToken.getCredentials();
        //让具体认证类去认证
        UserDetails user = userDetailsService.loadUserByUsername(username); 
        boolean matches = passwordEncoder.matches(password, user.getPassword());
        if (!matches) {
            ResMsg.throwException(AuthExceptionGroup.AUTH_ERROR);
        }
        //填充Authentication
        NamePassAuthenticationToken authenticationResult = new NamePassAuthenticationToken(user, password, user.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }

    @Override
    //指定具体的Authentication
    //根据你指定的Authentication来找到具体的Provider
    public boolean supports(Class<?> authentication) {
        return NamePassAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

SecurityConfigurerAdapter

接着就是填充配置了

@Component
public class NamePassAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(HttpSecurity http) {
        //phonePass provider
        NamePassAuthenticationProvider provider = new NamePassAuthenticationProvider();
        provider.setUserDetailsService(customUserDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        http.authenticationProvider(provider);
    }
}

接下来就是导入配置了

通常都会有一个实现了WebSecurityConfigurerAdapter的配置类

把配置类注入进来

@Autowired
private NamePassAuthenticationSecurityConfig namePassAuthenticationSecurityConfig; 
    
protected void configure(HttpSecurity http) throws Exception {
  http.apply(namePassAuthenticationSecurityConfig);
}

UserDetailsService

UserDetailsService是具体的认证实现类

这个类就非常熟悉了,只需要实现他的loadUserByUsername方法,就可以实现认证了

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AuthmsViewAccount account = accountService.getAccount(username);
        if(account == null) {
            ResMsg.throwException(AUTH_ERROR);
        }

        if (account.getStatus() != 1) {
            ResMsg.throwException(ACCOUNT_HAS_BANED);
        }

        String spliceStaffInfo = String.format("%d-%s",account.getAccountId(),account.getUsername());
//只要Collection<? extends GrantedAuthority> authorities
//这个参数不为空,就表明认证通过,所以空集合也可以通过
        return new User(spliceStaffInfo,account.getPassword(), AuthorityUtils.NO_AUTHORITIES);
    }

把认证结果填充到上下文中

TokenFilter

如果结合了Token,那么需要从token中识别该用户

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

    String bearerToken = resolveToken(request);

    if (bearerToken != null && !"".equals(bearerToken.trim()) && SecurityContextHolder.getContext().getAuthentication() == null) {
        //从redis中获取该用户
        NamePassAuthenticationToken namePassAuthenticationToken = authRedisHelper.get(bearerToken);
        if(namePassAuthenticationToken != null) {
            //将信息保存到上下文中
 SecurityContextHolder.getContext().setAuthentication(namePassAuthenticationToken);
        }
    }

    chain.doFilter(request, response);
}

private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
            return bearerToken.substring(7);
        }
        return null;
    }
public NamePassAuthenticationToken get(String bearerToken){
    String spliceStaffInfo = (String)redisRepository.get(formatKey(bearerToken));
    if(spliceStaffInfo == null) {
        return null;
    }
    return new NamePassAuthenticationToken(new AuthStaff(spliceStaffInfo),null,AuthorityUtils.NO_AUTHORITIES);
}

登录过程

在登录的时候,就需要用到这个自定义的认证器了

// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 NamePassAuthenticationToken
NamePassAuthenticationToken authenticationToken = new NamePassAuthenticationToken(user.getUsername(), user.getPassword());

//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象 
//AuthenticationManager会通过你传入的authenticationToken来找到具体的Provider
Authentication authentication = authenticationManager.authenticate(authenticationToken);
//填充用户信息到secrity中的user里
User principal = (User) authentication.getPrincipal();
//获取认证后的信息
NamePassAuthenticationToken namePassAuthenticationToken = new NamePassAuthenticationToken(new AuthStaff(principal.getUsername()), null, authentication.getAuthorities());
// 生成token
String bearerToken = IdUtil.fastSimpleUUID();
// 加载到reids
authRedisHelper.set(bearerToken, namePassAuthenticationToken);

这样就实现了自定义的认证器了

到此这篇关于Spring Security自定义认证器的文章就介绍到这了,更多相关Spring Security自定义认证器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringSecurity自定义认证器的实现代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Asp.net Core中实现自定义身份认证的示例代码

Asp.Net Core中虽然集成了许多常用的身份认证,但很多时候,我们还是需要实现自己的身份认证接口,本文这里就简单的介绍下如何实现自定义身份认证接口。 首先写一个简单的接口。[Authorize] [HttpGet] public ob
2022-06-07

Android 自定义dialog的实现代码

Android 自定义dialog的实现代码 搜索相关关键字网上一大堆实现,但是看完总觉得缺胳膊少腿,绕了不少弯路,终于弄好了自定义dialog。把自己整合的完整代码发上来。要点:1、设置自定义dialog的布局文件my_dialog.xm
2022-06-06

Android自定义View实现验证码

本文章是基于鸿洋的Android 自定义View (一) 的一些扩展,以及对Android自定义View构造函数详解里面内容的一些转载。 首先我们定义一个declare-styleable标签declare-styleable标签的作用是给
2022-06-06

.Net Core中如何写自定义认证实现

今天就跟大家聊聊有关.Net Core中如何写自定义认证实现,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、起因 最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认
2023-06-28

SpringSecurity定义多个过滤器链的操作代码

Spring Security 是 Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富,今天通过本文给大家介绍SpringSecurity定义多个过滤器链的实例,感兴趣的朋友跟随小编一起看看吧
2023-05-17

Android实现自定义验证码输入框效果(实例代码)

这里提一下,这个当时也是在网上看到一个博主写的代码改了下用在我么项目中的验证码输入框。博主的地址不记得了这里只能顺带标注一下。。。 效果图如下:就是这个酱紫 直入主题,代码如下: xml布局:
2022-06-06

Android 自定义弹出框实现代码

废话不多说了,直接给大家上关键代码了。- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self s
2022-06-06

Android AlertDialog自定义样式实现代码

Android AlertDialog自定义样式 像列表这种选择项的弹出式对话框,要改变样式一般都采取重写layout方式 今天才了解到 其实可以自定义样式,与大家分享下,其实很简单AlertDialog.Builder builder =
2022-06-06

Android自定义日历Calender代码实现

产品要做签到功能,签到功能要基于一个日历来进行,所以就根据 要求自定义了一个日历自定义控件相信做android都知道:(1)首先创建一个类,继承一个容器类或者是一个控件 (2)然后就是你需要设置的属性等的,在attrs文件夹中 (3)然后就
2022-06-06

Android自定义View实现随机验证码

对于android开发来说自定义View还是一个比较重要的技能,所以在这里写一篇自定义View入门的文章,也是实现一个相对简单的随机产生验证码的功能: 自定义View主要也就分为几步 1.自定义View的属性 2.在我们的自定义的布局
2022-06-06

Android自定义相机界面的实现代码

我们先实现拍照按钮的圆形效果哈,Android开发中,当然可以找美工人员设计图片,然后直接拿进来,不过我们可以自己写代码实现这个效果哈,最常用的的是用layout-list实现图片的叠加,我们这个layout命名为btn_take_phot
2022-06-06

antDesign自定义分页样式的实现代码

这篇文章主要介绍了antDesign自定义分页样式的实现代码,这里用到了自定义指令,如果大家用不到可以按照自己的实际效果开发,本文通过实例代码给大家详细讲解,需要的朋友可以参考下
2022-11-13

PopupWindow自定义位置显示的实现代码

一、概述在Android中弹出式菜单(以下称弹窗)是使用十分广泛的一种菜单呈现方式,弹窗为用户交互提供了便利。关于弹窗的实现大致有以下两种方式AlertDialog和PopupWindow,当然网上也有使用Activity并配合Dialog
2023-05-30

C#实现自定义屏保的示例代码

这篇文章主要为大家详细介绍了如何利用C#实现自定义屏保的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
2022-12-31

基于SpringSecurity的@PreAuthorize怎么实现自定义权限校验

这篇文章主要介绍“基于SpringSecurity的@PreAuthorize怎么实现自定义权限校验”,在日常操作中,相信很多人在基于SpringSecurity的@PreAuthorize怎么实现自定义权限校验问题上存在疑惑,小编查阅了各
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录