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. 换根 DP 学习笔记

    前言 没脑子选手什么都不会. 正文 先来写一下换根 DP 的特点或应用方面: 不同的点作为树的根节点,答案不一样. 求解答案时要求出每一个节点的信息. 无法通过一次搜索完成答案的求解,因为一次搜索只能 ...

  2. cx_Oracle.DatabaseError: ORA-28759: failure to open file

    找了好久这个问题,有人说是tcps的问题,需要自己生成证书什么的,后来才发现原来是 钱包文件路径 的问题,钱包文件解压后必须放在instantclien/network/admin下,在Windows ...

  3. docker仓库之harbor的基本使用(二)

    1 1.配置docker使用harbor仓库上传下载镜像 2 #注意:如果我们配置的是https的话,本地docker就不需要任何操作就可以访问harbor 3 测试机器 4 root@ubuntu1 ...

  4. noi-2.2基本算法之递归和自调用函数:放苹果

    先看一下题目: http://noi.openjudge.cn/ch0202/666/http://noi.openjudge.cn/ch0202/666/ 把M个同样的苹果放在N个同样的盘子里,允许 ...

  5. P4289 【一本通提高篇广搜的优化技巧】[HAOI2008]移动玩具

    [HAOI2008]移动玩具 题目描述 在一个 4 × 4 4\times4 4×4 的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方 ...

  6. 项目配置yaml

    springboot的一些配置 #当循环调用时,就会报错 spring.main.allow-circular-references=true #配置mvc是需要使用一个@EnableWebMvc,不 ...

  7. WSL2安装Ubuntu20.04

    前言:听说WSL2需要Window版本在1904以上(我的window版本是1909,所以未能验证真实性) 启用WSL 控制面板 → 程序 → 程序和功能 → 启用或关闭Windows功能 勾选 适用 ...

  8. 聊聊如何用 Redis 实现分布式锁?

    作者:小林coding 计算机八股文网站:https://xiaolincoding.com 哈喽,我是小林. 今天跟大家聊聊两个问题: 如何用 Redis 实现分布式锁? Redis 是如何解决集群 ...

  9. 数据结构(C语言版)严蔚敏->排序

    @ 目录 1. 插入排序 1.1 直接插入排序 1.2 折半插入排序 1.3 希尔排序(Shell Sort) 2.交换排序 2.1 冒泡排序 2.2 快速排序 3. 选择排序 3.1 简单选择排序 ...

  10. 使用rust调用c++静态库并编译nodejs包

    在项目上经常要用到身份证阅读器.护照阅读仪.指纹仪等各种品牌硬件,假如每套系统的都做集成开发那代码的维护成本将变得很高,为此采用rust来调用厂家提供的sdk c++开发包并封装成nodejs包,用f ...