springboot+security整合(1)
说明 springboot 版本 2.0.3
源码地址:点击跳转
系列
一、 介绍
Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在 Spring 应用上下文中配置的 Bean,充分利用了 Spring IoC,DI(控制反转 Inversion of Control ,DI:Dependency Injection 依赖注入)和 AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
二、 环境搭建
建立 springboot2 项目,加入 security 依赖,mybatis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
数据库为传统的用户--角色--权限,权限表记录了 url 和 method,springboot 配置文件如下:
mybatis:
type-aliases-package: com.example.demo.entity
server:
port: 8081
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
http:
encoding:
charset: utf-8
enabled: true
springboot 启动类中加入如下代码,设置路由匹配规则。
@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false) //设置路由是否后缀匹配,譬如/user能够匹配/user.,/user.aa
.setUseTrailingSlashMatch(false); //设置是否后缀路径匹配,比如/user能够匹配/user,/user/
}
三、 security 配置
默认情况下 security 是无需任何自定义配置就可使用的,我们不考虑这种方式,直接讲如何个性化登录过程。
1、 建立 security 配置文件,目前配置文件中还没有任何配置。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
2、 个性化登录,security 中的登录如下:

- security 需要一个 user 的实体类实现
UserDetails接口,该实体类最后与系统中用户的实体类分开,代码如下:
public class SecurityUser implements UserDetails{
private static final long serialVersionUID = 1L;
private String password;
private String name;
List<GrantedAuthority> authorities;
public SecurityUser(string name,string password) {
this.id = id;
this.password = password;
this.name = name;
this.age = age;
}
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.authorities;
}
@Override //获取校验用户名
public String getUsername() {
return String.valueOf(this.id);
}
@Override //获取校验用密码
public String getPassword() {
return password;
}
@Override //账户是否未过期
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override //账户是否未锁定
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override //帐户密码是否未过期,一般有的密码要求性高的系统会使用到,比较每隔一段时间就要求用户重置密码
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override //账户是否可用
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
}
- 编写了实体类还需要编写一个服务类 SecurityService 实现
UserDetailsService接口,重写 loadByUsername 方法,通过这个方法根据用户名获取用户信息,代码如下:
@Component
public class SecurityUserService implements UserDetailsService {
@Autowired
private JurisdictionMapper jurisdictionMapper;
@Autowired
private UserMapper userMapper;
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("登录用户id为:{}",username);
int id = Integer.valueOf(username);
User user = userMapper.getById(id);
if(user==null) {
//抛出错误,用户不存在
throw new UsernameNotFoundException("用户名 "+username+"不存在");
}
//获取用户权限
List<GrantedAuthority> authorities = new ArrayList<>();
List<Jurisdiction> jurisdictions = jurisdictionMapper.selectByUserId(id);
for(Jurisdiction item : jurisdictions) {
GrantedAuthority authority = new MyGrantedAuthority(item.getMethod(),item.getUrl());
authorities.add(authority);
}
SecurityUser securityUser = new SecurityUser(user.getName(),user.getPassword(),authority):
user.setAuthorities(authorities);
return securityUser;
}
}
- 通常我们会对密码进行加密,所有还要编写一个 passwordencode 类,实现 PasswordEncoder 接口,代码如下:
@Component
public class MyPasswordEncoder implements PasswordEncoder {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override //不清楚除了在下面方法用到还有什么用处
public String encode(CharSequence rawPassword) {
return StringUtil.StringToMD5(rawPassword.toString());
}
//判断密码是否匹配
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(this.encode(rawPassword));
}
}
3、 编辑配置文件
- 编写 config Bean 以使用上面定义的验证逻辑,securityUserService、myPasswordEncoder 通过@Autowired 引入。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityUserService)
.passwordEncoder(myPasswordEncoder);
}
- 然后编写 configure Bean(和上一个不一样,参数不同),实现 security 验证逻辑,代码如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf() //跨站
.disable() //关闭跨站检测
.authorizeRequests()//验证策略策略链
.antMatchers("/public/**").permitAll()//无需验证路径
.antMatchers("/login").permitAll()//放行登录
.antMatchers(HttpMethod.GET, "/user").hasAuthority("getAllUser")//拥有权限才可访问
.antMatchers(HttpMethod.GET, "/user").hasAnyAuthority("1","2")//拥有任一权限即可访问
//角色类似,hasRole(),hasAnyRole()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/public/unlogin") //未登录跳转页面,设置了authenticationentrypoint后无需设置未登录跳转页面
.loginProcessingUrl("/public/login")//处理登录post请求接口,无需自己实现
.successForwardUrl("/success")//登录成功转发接口
.failureForwardUrl("/failed")//登录失败转发接口
.usernameParameter("id") //修改用户名的表单name,默认为username
.passwordParameter("password")//修改密码的表单name,默认为password
.and()
.logout()//自定义登出
.logoutUrl("/public/logout") //自定义登出api,无需自己实现
.logoutSuccessUrl("public/logoutSuccess")
}
到这里便可实现 security 与 springboot 的基本整合。
四、实现记住我功能
1、 建表
记住我功能需要数据库配合实现,首先要在数据库建一张表用户保存 cookie 和用户名,数据库建表语句如下:不能做修改
CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
)
2、 编写 rememberMeservice Bean
代码如下:
@Bean
public RememberMeServices rememberMeServices(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
PersistentTokenBasedRememberMeServices rememberMeServices =
new PersistentTokenBasedRememberMeServices("INTERNAL_SECRET_KEY",securityUserService,jdbcTokenRepository);
//还可设置许多其他属性
rememberMeServices.setCookieName("kkkkk"); //客户端cookie名
return rememberMeServices;
}
dataSource 为@Autowired 引入
3、 配置文件设置 remember
在 config(HttpSecurity http)中加入记住我功能
.rememberMe()
.rememberMeServices(rememberMeServices())
.key("INTERNAL_SECRET_KEY")
在登录表单中设置 remember-me 即可实现记住我功能。
本文原创发布于:https://www.tapme.top/blog/detail/2018-08-20-10-38
springboot+security整合(1)的更多相关文章
- springboot+security整合(3)自定义鉴权
说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...
- springboot+security整合(2)自定义校验
说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...
- Springboot security cas整合方案-原理篇
前言:网络中关于Spring security整合cas的方案有很多例,对于Springboot security整合cas方案则比较少,且有些仿制下来运行也有些错误,所以博主在此篇详细的分析cas原 ...
- Springboot security cas整合方案-实践篇
承接前文Springboot security cas整合方案-原理篇,请在理解原理的情况下再查看实践篇 maven环境 <dependency> <groupId>org.s ...
- springboot+maven整合spring security
springboot+maven整合spring security已经做了两次了,然而还是不太熟悉,这里针对后台简单记录一下需要做哪些事情,具体的步骤怎么操作网上都有,不再赘述.1.pom.xml中添 ...
- Springboot security cas源码陶冶-CasAuthenticationFilter
Springboot security cas整合方案中不可或缺的校验Filter类或者称为认证Filter类,其内部包含校验器.权限获取等,特开辟新地啃啃 继承结构 - AbstractAuthen ...
- SpringBoot系列九:SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 服务整合 2.背景 在进行项目开发的时候经常会遇见以下的几个问题:需要进行邮件发送.定时的任务调 ...
- Spring Boot与Spring Security整合后post数据不了,403拒绝访问
http://blog.csdn.net/sinat_28454173/article/details/52251004 *************************************** ...
- SpringBoot security关闭验证
SpringBoot security关闭验证 springboot2.x security关闭验证https://www.cnblogs.com/guanxiaohe/p/11738057.html ...
随机推荐
- Spring Cloud Eureka源码分析 --- client 注册流程
Eureka Client 是一个Java 客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的.使用轮询负载算法的负载均衡器. 在应用启动后,将会向Eureka Serve ...
- JVM 线上故障排查基本操作--CPU飙高
JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...
- iOS - 点击按钮实现简单的复制功能
UIPasteboard使用 基本使用: - (void)copyClick { UIPasteboard *pab = [UIPasteboard generalPasteboard]; pab.s ...
- 手工下载php的composer软件包,如何让项目自动加载包里的类
有的时候需要手工下载php的composer包 1.将下载好的包放到项目的vendor目录下,比如包名:pinguo/php-aop 2.然后查看软件包目录(vendor/pinguo/php-aop ...
- [LeetCode] 186. Reverse Words in a String II 翻转字符串中的单词 II
Given an input string, reverse the string word by word. A word is defined as a sequence of non-space ...
- Tomcat免安装版执行tomcat9.exe闪退
Tomcat免安装版点击startup.bat可成功启动,但是执行tomcat9.exe时却闪退,这是因为免安装版的tomcat不会自动把tomcat注册到windows服务里,需要手动注册. 解决办 ...
- ArrayPool数组池、Span<T>结构
数组(ArrayPool数组池.Span<T>结构) 目录 前言 简单的数组.多维数组.锯齿数组 Array类 ArrayPool数组池 Span Span介绍 Span切片 使用Span ...
- 基于thinkphp5框架做一个可以区别开发、测试、生产三种环境的配置加载
在日常的开发测试中我们经常会遇到本地开发和测试或者线上配置参数不同的场景,必要你要是使用一个三方的支付,它的本地测试和线上的key值或者账号存在不同.最基本的做法是本地用测试参数,提交到测试的时候再改 ...
- [Python]MySQLdb for Python使用指南/Python的数据库操作
网站就是要和数据库进行交互,否则什么都不用做了...今天我们来看一个叫MySQLdb的库,这个用来和MySQL数据库进行交互.可以从这里获得这个库http://sourceforge.net/proj ...
- BugkuCTF~Misc~WriteUp
1.签到 get flag: Qftm{You should sign in} 2.这是一张单纯的图片 查看图片十六进制 提去特殊字符串进行解码 get flag: key{you are right ...