SpringSecurity web

安全管理框架

需要依赖多

shiro 轻量

  • SSM+Shiro
  • SpringBoot/SpringCloud+SpringSecurity

配置用户名密码

  • 配置文件

  • extends WebSecurityConfigurerAdapter
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123");
auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
} @Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
} }
  • 自定义实现类配置
  1. 创建配置类,设置使用哪个userDetailsService实现类
  2. 编写实现类,返回User对象,User对象有用户名密码和操作权限
  3. 自定义登录页面
@Configuration
public class SecurityConfig1 extends WebSecurityConfigurerAdapter { @Autowired
private UserDetailsService userDetailsService; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
} @Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
} }
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService { @Autowired
private UsersMapper usersMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",username);
Users users = usersMapper.selectOne(queryWrapper);
if(users == null ){
throw new UsernameNotFoundException("用户名不存在");
} //查数据库
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); // return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
}
}

设置访问权限

.antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问

.antMatchers("/test/index").hasAnyAuthority("admins,manager")//有其中一个权限即可访问

.antMatchers("/test/index").hasRole("sale")//为ROLE_sale

.antMatchers("/test/index").hasAnyRole("sale,customer")//多个角色的任何一个就可访问

//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
    @Override
protected void configure(HttpSecurity http) throws Exception {
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html"); http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
.antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
}

注解授权

启动类上加注解

@EnableGlobalMethodSecurity(securedEnabled = true)

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)
public class Springsecuritydemo1Application { public static void main(String[] args) {
SpringApplication.run(Springsecuritydemo1Application.class, args);
} }

@Secured

具有某个角色可以用访问该方法

@GetMapping("update")
@Secured({"ROLE_sale","ROLE_manager"})
public String update() {
return "hello update";
}

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

@PreAuthorize

执行方法前校验admins

@GetMapping("update")
//@Secured({"ROLE_sale","ROLE_manager"})
@PreAuthorize("hasAnyAuthority('admins')")
public String update() {
return "hello update";
}

@PostAuthorize

执行方法后校验

@PreFilter

@PostFilter

用户注销

修改配置类protected void configure(HttpSecurity http) throws Exception加上

http.logout().logoutUrl("/logout").logoutSuccessUrl("/index/add").permitAll();

自动登录

  1. Cookie
  2. 安全框架机制实现自动登录

原理:

  1. 认证成功->浏览器cookie存加密字符串,数据库存cookie的加密串,用户信息字符串
  2. 再次访问->获取cookie信息,拿着cookie信息到数据库进行比对,如果查询到对应信息,认证成功,就可以登录。

springsecurity实现:

  • 创建表
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`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
  • 配置类注入数据源,配置操作数据库对象
    @Autowired
private DataSource dataSource; @Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource); //jdbcTokenRepository.setCreateTableOnStartup(true); //设置自动创建token表
return jdbcTokenRepository;
}
  • .and().rememberMe().tokenRepository(persistentTokenRepository())
    .tokenValiditySeconds(60)//设置有效时长
    .userDetailsService(userDetailsService)//设置userDetailsService操作数据库
    @Override
protected void configure(HttpSecurity http) throws Exception { //配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html"); //
http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/add").permitAll(); http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/success.html").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
// .antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问
// .antMatchers("/test/index").hasAnyAuthority("admins,manager")
//ROLE_xxx
.antMatchers("/test/index").hasRole("sale")
// .anyRequest().authenticated()
.and().rememberMe().tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60)//设置有效时长
.userDetailsService(userDetailsService)//设置userDetailsService操作数据库
.and().csrf().disable();//关闭csrf防护
}
  • 登录页面添加复选框 name必须为"remember-me"
<input type="checkbox" name="remember-me">自动登录

CSRF

跨站请求伪造

跨站请求攻击,简单地说,是攻击者通过一些技术手段七篇用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行

->>web中用户身份验证的一个漏洞:简单的身份验证之恶能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

实现CSRF原理:(只对"GET","HEAD","TRACE","OPTIONS"防护)

生成csrfToken保存到HttpSession,每次访问把带着过来的token和session存储的token是否一样

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(HttpServletResponse.class.getName(), response);
CsrfToken csrfToken = this.tokenRepository.loadToken(request);//创建token
boolean missingToken = csrfToken == null;
if (missingToken) {
csrfToken = this.tokenRepository.generateToken(request);
this.tokenRepository.saveToken(csrfToken, request, response);
} request.setAttribute(CsrfToken.class.getName(), csrfToken);
request.setAttribute(csrfToken.getParameterName(), csrfToken);//得到表单传递过来的token
//requireCsrfProtectionMatcher指定了防护的请求方式
if (!this.requireCsrfProtectionMatcher.matches(request)) {
filterChain.doFilter(request, response);
} else {
String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
} if (!csrfToken.getToken().equals(actualToken)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request));
} if (missingToken) {
this.accessDeniedHandler.handle(request, response, new MissingCsrfTokenException(actualToken));
} else {
this.accessDeniedHandler.handle(request, response, new InvalidCsrfTokenException(csrfToken, actualToken));
} } else {
filterChain.doFilter(request, response);
}
}
}

Spring Security微服务权限

基本概念

单点登录:一次登录其他模块能直接操作

  • 基于Session,那么Spring Security会对cookie里的sessionId进行解析,找到服务器存储的session信息,然后判断当前用户是否符合请求的要求
  • 如果是token,则是解析出token,然后将当前请求加入到SpringSecurity管理的权限信息中去

查出权限列表,存入到redis中,根据用户名生成token再放入到cookie中,在header放token,springsecurity从header获取token,从token获取用户名,根据用户名从redis获取权限列表。由springsecurity给当前与用户赋予权限,可以进行相应操作。

案例

创建工程

登录

添加角色

为角色分配菜单

添加用户分配角色

SpringSecurity基本使用的更多相关文章

  1. spring mvc 和spring security配置 spring-servlet.xml和spring-security.xml设置

    spring-servlet.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  2. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)

    一直希望能够搭建一个完整的,基础Web框架,方便日后接一些外快的时候,能够省时省力,终于花了一周的时间,把这个东西搞定了.特此写下此博客,一来是纪念,二来是希望能够为别人提供方便.顺带说一下,恩,组合 ...

  3. 【JavaWeb】SSM+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(六)

    Showings 我个人的项目,当前不断地在更新. 我希望做成一个好项目,同时,也是在锻炼自己的技术. 在项目中发现问题,学习知识,是比较可取的一条路子. 这样学习到的知识,虽然分散,但是都很实用,而 ...

  4. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(五)

    SpringSecurity(2) 好久没有写了,之前只写了一半,我是一边开发一边写Blog一边上班,所以真心没有那么多时间来维护Blog,项目已经开发到编写逻辑及页面部分了,框架基本上已经搭建好不会 ...

  5. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(四)

    SpringSecurity(1) 其实啊,这部分我是最不想写的,因为最麻烦的也是这部分,真的是非常非常的麻烦.关于SpringSecurity的配置,让我折腾了好半天,网上的配置方式一大把,但总有一 ...

  6. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(一)

    Spring+MyBatis 首先要搭建的是Spring+MyBatis的整合框架,毕竟Spring是整个Web框架的核心部位,而数据库操作是一切测试的基础嘛. 目录结构 ━java ┣ contro ...

  7. SSO单点登录Spring-Security & CAS使用手册

    1.1概述 1.1.1单点登录介绍 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可 ...

  8. spring4.2.3+mybatis+spring-security配置文件

    1.web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&qu ...

  9. springmvc+spring-security+mybatis +redis +solar框架抽取

    参考文章:Spring MVC 3 深入总结: 第二章 Spring MVC入门 —— 跟开涛学SpringMVC 参考博客:http://www.cnblogs.com/liukemng/categ ...

  10. 安全框架 SpringSecurity 和 Shiro 对比

    突然再次很想理一下权限的事,但是实在不知道实际情况选哪个框架好,现在整理下网上的资料,做一下对比. 1.Spring-security 对spring 结合较好,如果项目用的springmvc ,使用 ...

随机推荐

  1. Node.js精进(7)——日志

    在 Node.js 中,提供了console模块,这是一个简单的调试控制台,其功能类似于浏览器提供的 JavaScript 控制台. 本系列所有的示例源码都已上传至Github,点击此处获取. 一.原 ...

  2. 下载Chrome离线安装包

    https://www.google.com/chrome/thankyou.html?standalone=1&platform=mac&installdataindex=defau ...

  3. 2022-07-09 第六组 润土 CSS学习笔记

    HTML:用来描述网页的一种语言. 超文本语言.动画.音频.视频.特效.超链. 用标签定义网页 浏览器 流行浏览器: IE微软宣布永久关闭 firefox火狐 Chrom谷歌 Sarifi vscod ...

  4. Solution -「CF645F」Cowslip Collections

    设 \(f(i)\) 表示大小为 \(k\),\(\gcd\) 为 \(i\) 的方案数.\(F(i)\) 表示大小为 \(k\),\(\gcd\) 为 \(i\) 的倍数的方案数. 不难看出:\(F ...

  5. 转换流的原理和OutputStreamWriter介绍&代码实现

    转换流的原理 OutputStreamWriter介绍&代码实现 package com.yang.Test.ReverseStream; import java.io.FileNotFoun ...

  6. TFRecord的Shuffle、划分和读取

    对数据集的shuffle处理需要设置相应的buffer_size参数,相当于需要将相应数目的样本读入内存,且这部分内存会在训练过程中一直保持占用.完全的shuffle需要将整个数据集读入内存,这在大规 ...

  7. python将命令输出写入文件或临时缓存

    python将命令输出写入文件 将文件写入到对应文件,方便后期处理或保存 def write_file(file_path): with open(file=file_path, mode=" ...

  8. typora的第一天

    一级标题 二级标题 三级标题 ..... 表格 java spring mybatis 代码 java代码 public void Hello(){ } 字体 hello word! hello wo ...

  9. springboot整合xxl-job分布式定时任务【图文完整版】

    一.前言 定时任务有很多种,有一些大的框架也有一些简单的实现. 比如常见的: JDK的Timer和TimerTask Quartz异步任务调度框架 分布式定时任务XXL-JOB Spring Task ...

  10. vue脚手架创建项目后使用路由报错Object(...) is not a function问题

    在这之前我做过的vue项目没有这种问题,今天突然出现这个问题,也检查了很久的代码,最后解决我也不知道我是哪一步做错了 首先我是创建的vue2项目,基本操作跟平常一样,在运用路由跳转的时候遇到这个问题 ...