​在前面的文章中,我们自定义了一些CA登录相关的类,如 CertificateAuthorityAuthenticationTokenCertificateAuthorityAuthenticationFilterCertificateAuthorityDaoAuthenticationProvider等。但是,由于诸多条件的不具备,也就没有办法演示。

不过,目前一个新登录方式所需要的逻辑基本都介绍过了,下面,就利用这些已经自定义的类,来尝试如何自定义个新的登录方式-CA登录。并且,CA登录需要与默认的用户名密码登录方式共存,也即用户可以自由选择何种登录方式来登录系统。

登录页面改造

首先,我们来改造一下登录页面,添加CA登录方式。

<div class="login-form"><ul class="nav nav-tabs mb-3" role="tablist"><li class="nav-item"><a class="nav-link active" href="#login" data-toggle="tab">用户登录</a></li><li class="nav-item"><a class="nav-link" href="#ca_login" data-toggle="tab">CA登录</a></li></ul><div class="tab-content"><div id="login" class="tab-pane active"><form th:action="@{/login}" method="post" th:method="post" class="mt-1"><div class="form-group"><input type="text" class="form-control" name="username" placeholder="用户名"></div><div class="form-group"><input type="password" class="form-control" name="password" placeholder="密码"></div><div class="checkbox"><label><input type="checkbox"> 记住我</label></div><button type="submit" class="btn btn-primary btn-block mb-1 mt-1">登录</button><p class="text-muted text-center"> <a href="login.html#"><small>忘记密码了?</small></a> | <a href="#">注册一个新账号</a></p></form></div><div id="ca_login" class="tab-pane"><form th:action="@{/certificate_authority_login}" method="post" th:method="post" class="mt-1"><div class="form-group"><input type="text" class="form-control" name="signature" value="3691308F2A4C2F6983F2880D32E29C84" readonly /></div><button type="submit" class="btn btn-primary btn-block mb-1 mt-1">登录</button><p class="text-muted text-center"> <a href="login.html#"><small>忘记密码了?</small></a> | <a href="#">注册一个新账号</a></p></form></div></div>
</div>

页面效果如下:

使用CA签名获取用户信息

首先,需要修改 SYS_USER 表结构,新增 signature 字段,即CA签名,当然,也可以是能标识CA唯一性的其它属性。

alter table SYS_USER add signature varchar(60) comment 'ca签名';

接下来,把之前用户名为 zhangsan 的数据,添加 signature 字段值。

UPDATE sys_user SET signature = '3691308F2A4C2F6983F2880D32E29C84' WHERE ID = '2031a4adc78942d59188cea7927e6304';

然后,UserDao 新增使用 signature 查询用户信息的方法。

public SysUser getBySignature(String signature) {String sql = "select id, name, username, password, age, state from sys_user where signature = :signature";
​Map<String, Object> paramMap = new HashMap<>();paramMap.put("signature", signature);
​return get(sql, paramMap, SysUser.class);
}

最后,自定义 UserDetailsService 接口实现 CertificateAuthorityJdbcUserDetailsService,以注入 UserDao 查询用户信息。

public UserDetails loadUserByUsername(String signature) throws UsernameNotFoundException {SysUser sysUser = this.userDao.getBySignature(signature);
​User.UserBuilder builder = User.builder().username(sysUser.getUsername()).password(sysUser.getPassword());
​List<String> roles = this.roleDao.listRoleCodeByUserId(sysUser.getId());
​builder.roles(roles == null ? new String[] {} : roles.toArray(new String[] {}));
​return builder.build();
}

Spring Security配置改造

最后,把CA登录相关的配置添加到 Spring Security 配置中即可。

@EnableWebSecurity
@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
​......
​@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(certificateAuthorityDaoAuthenticationProvider()).userDetailsService(customJdbcUserDetailsService()).passwordEncoder(new BCryptPasswordEncoder());}
​private AbstractAuthenticationProcessingFilter certificateAuthorityAuthenticationFilter() throws Exception {CertificateAuthorityAuthenticationFilter authorityAuthenticationFilter = new CertificateAuthorityAuthenticationFilter();authorityAuthenticationFilter.setAuthenticationSuccessHandler(certificateAuthorityAuthenticationSuccessHandler());authorityAuthenticationFilter.setAuthenticationFailureHandler(certificateAuthorityAuthenticationFailureHandler());authorityAuthenticationFilter.setAuthenticationManager(authenticationManager());return authorityAuthenticationFilter;}
​private AuthenticationProvider certificateAuthorityDaoAuthenticationProvider() {CertificateAuthorityDaoAuthenticationProvider certificateAuthorityDaoAuthenticationProvider = new CertificateAuthorityDaoAuthenticationProvider();certificateAuthorityDaoAuthenticationProvider.setUserDetailsService(certificateAuthorityJdbcUserDetailsService());return certificateAuthorityDaoAuthenticationProvider;}
​private UserDetailsService certificateAuthorityJdbcUserDetailsService() {CertificateAuthorityJdbcUserDetailsService userDetailsService = new CertificateAuthorityJdbcUserDetailsService();userDetailsService.setUserDao(userDao);userDetailsService.setRoleDao(roleDao);return userDetailsService;}
​private AuthenticationSuccessHandler certificateAuthorityAuthenticationSuccessHandler() {SavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();authenticationSuccessHandler.setDefaultTargetUrl("/index");return authenticationSuccessHandler;}
​private AuthenticationFailureHandler certificateAuthorityAuthenticationFailureHandler() {SimpleUrlAuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler();authenticationFailureHandler.setDefaultFailureUrl("/login_fail");return authenticationFailureHandler;}
​......
​
}

登录尝试

首先,我们尝试CA登录方式。点击登录页面的CA登录TAB页,切换到CA登录方式,此时,CA的相关信息可正常显示到页面中(由CA厂商提供的API从插入电脑USB口的CA Key中获取)。

然后,点击 登录 按钮(注意,真实情况下,需要输入CA Key的密码,此处省略)系统正常登录。

查看个人中心,用户正确无误。

接下来,退出登录,切换到用户登录TAB页,使用用户名密码方式再次登录,同样可以正常登录系统,并无影响。两种登录方式完美共存。

CA登录方式实现及配置完成。

其它详细源码,请参考文末源码链接,可自行下载后阅读。

我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!

如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!

源码

github

https://github.com/liuminglei/SpringSecurityLearning/tree/master/28

gitee

https://gitee.com/xbd521/SpringSecurityLearning/tree/master/28

史上最简单的Spring Security教程(二十八):CA登录与默认用户名密码登录共存详细实现及配置相关推荐

  1. 史上最简单的Spring Security教程(十九):AccessDecisionVoter简介及自定义访问权限投票器

    为了后续对 AccessDecisionManager 的介绍,我们先来提前对 AccessDecisionVoter 做个简单的了解,然后,在捎带手自定义一个 AccessDecisionVoter ...

  2. microsoftsql新建登录用户登录失败_史上最简单的Spring Security教程(九):自定义用户登录失败页面...

    生活中肯定存在这样的场景,在登录某个网站时,难免会忘记密码,或是验证码输入错误,造成多次尝试.所以,有必要适度的提醒用户,到底是什么原因造成了登录失败,如用户名密码不正确.验证码错误等等.由于 Spr ...

  3. 史上最简单的Spring Security教程(八):用户登出成功LogoutSuccessHandler高级用法

    ​大多数业务场景下,自定义登出成功页面也满足不了一些要求,更别提默认的登出成功页面.这时候,就需要别的方案支持,幸运的是,Spring Security 框架还真就非常贴心的提供了这样一个接口 Log ...

  4. 史上最简单的 Spring MVC 教程(九)

    1 前言 在史上最简单的 Spring MVC 教程(五.六.七.八)等四篇博文中,咱们已经分别实现了"人员列表"的显示.添加.修改和删除等常见的增.删.改.查功能.接下来,也就是 ...

  5. 史上最简单的spark系列教程 | 完结

    <史上最简单的spark系列教程>系列: 与其说是教程不如说是改良后的个人学习笔记|| 教程参考自:<spark官方文档>,<spark快速分析>,<图解Sp ...

  6. 2010年史上最简单的做母盘教程

    2010年史上最简单的做母盘教程 辛苦了两个小时才把教程写完....写得不好大家多多包涵 其实做母盘是一件十分简单的事,只要大家敢去试就能成功的,这教程只给小白看的,老鸟路过指点一下. 本人是珠海信佑 ...

  7. Spring Boot教程(二十):Spring Boot使用String Task定时任务

    一.JAVA常见的几种定时任务比较 Timer:jdk自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让程序按照某一个频度执行, ...

  8. 如何在 CSDN 中增加博客访问量 史上最简单的博客教程 学会之后博客访问量直线上升。

    蹭热度 如何蹭是问题.下面分几点 你发布的有关技术是什么 你发布的是否是别人发布过的东西 你发布的东西在别人是怎样搜索的. 其实重点在流量,也就是点击.点击到位了,无论你文章来自哪里,或者说抄自哪里, ...

  9. 史上最简单的Git入门教程

    1. 版本控制系统简介 1.1 何为版本控制 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变,文件的版本号都将增加.除了记录版 ...

最新文章

  1. Mock session,cookie,querystring in ASB.NET MVC
  2. 判断字典中指定key是否存在
  3. 云计算学习总结(1)——PaaS云平台部署之在Centos7搭建Mesos+Zookeeper+Marathon+Docker单机集群...
  4. Query 中使用 text() 或者 html() 函数可bai以获取font or td 的内容:
  5. 【Arcpy】Python in ArcGIS
  6. (转载)计算机英语名词简释
  7. 2022-2028年中国差旅管理行业市场行情动态及投资潜力研究报告
  8. 13款用于Web的流行HTML5视频播放器
  9. Android等宽字体
  10. Android应用快捷方式
  11. html match函数,match函数 Match函数概述
  12. php采集今日头条,用php蓝天采集器抓取今日头条ajax的文章内容
  13. 日历教程:如何使Mac和iPhone上的日历显示国家节假日安排?
  14. RPG游戏制作-01-搭建游戏框架,初进游戏世界
  15. 企业邮箱邮件怎么撤回,邮件撤回怎么用?
  16. 【H.264/AVC视频编解码技术详解】二十三、帧间预测编码(1):帧间预测编码的基本原理
  17. css3切角文本框_CSS3如何实现4个切角
  18. 投影仪软件哪个好用?装上一起看TV,解锁追剧新体验
  19. 写于数学建模美赛准备期间
  20. oracle数据库测评

热门文章

  1. ABAP CS02物料BOM相关性分配实现
  2. Rx第六部分 测试
  3. mysql:取group by第一条数据
  4. 【java毕业设计】基于javaEE+原生Servlet+SqlServer的医院管理住院系统设计与实现(毕业论文+程序源码)——医院管理住院系统
  5. 系统之家安装windows虚拟机安装不成功原因及解决方法
  6. linux系统cpu性能测试工具
  7. 发票样板 html+css
  8. 计算机系统数据保存期限,哪种存储器存储数据时间长?
  9. android word分页,控制分页
  10. 硬件IIC和软件IIC区别