springsecurity简单学习
一、初识SpringSecurity
在springboot项目中加入spring security。
1、在pom.xml中加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、启动
在启动信息里面有一个自动生成的密码,默认用户名是user。
2018-10-18 15:31:10.241 INFO 4996 --- [ main] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: dd6f7b68-7409-4195-b908-b78cc9ec92af
此时我们就可以用user:dd6f7b68-7409-4195-b908-b78cc9ec92af登录了。
3、自己配置用户名密码
在application.yml中加入自定义配置
spring:
security:
user:
name: admin
password: admin
此时用户名密码就被定义成admin:admin了。
4、自定义配置类
更进一步,上面的安全模式只能有一个用户名密码,我们写一个自定义的配置类,配置多个用户名密码。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("user")
.roles("USER")
.and()
.withUser("admin")
.password("admin")
.roles("ADMIN")
.and()
.withUser("zhangsan")
.password("123456")
.roles("ADMIN");
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
@EnableWebSecurity注解开启Spring Security的功能
@EnableGlobalMethodSecurity(prePostEnabled = true)这个注解,可以开启security的注解,我们可以在需要控制权限的方法上面使用@PreAuthorize,@PreFilter这些注解
在configure(HttpSecurity http)方法里面,默认的认证代码是:
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
NoOpPasswordEncoder:springboot默认对密码会解析,加上这个是保持用户输入的密码
5、权限的简单使用
我们可以在方法上加上权限注解,如下:
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@RequestMapping("/home")
@PreAuthorize("hasRole('ADMIN')")
public String home() {
return "hello world";
}
}
常用权限
表达式 | 描述 |
---|---|
hasRole([role]) | 当前用户是否拥有指定角色。 |
hasAnyRole([role1,role2]) | 多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。 |
hasAuthority([auth]) | 等同于hasRole |
hasAnyAuthority([auth1,auth2]) | 等同于hasAnyRole |
Principle | 代表当前用户的principle对象 |
authentication | 直接从SecurityContext获取的当前Authentication对象 |
permitAll | 总是返回true,表示允许所有的 |
denyAll | 总是返回false,表示拒绝所有的 |
isAnonymous() | 当前用户是否是一个匿名用户 |
isRememberMe() | 表示当前用户是否是通过Remember-Me自动登录的 |
isAuthenticated() | 表示当前用户是否已经登录认证成功了。 |
isFullyAuthenticated() | 如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。 |
二、进阶 Security
用数据库存储用户和角色,实现安全认证。
1、先定义一个user:
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class User implements UserDetails {
private String username;
private String password;
private Collection<? extends GrantedAuthority> roles;
public Collection<? extends GrantedAuthority> getRoles() {
return roles;
}
public void setRoles(Collection<? extends GrantedAuthority> roles) {
this.roles = roles;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
2、定义一个service:
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class MyUserDetailsServiceimp implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
List<SimpleGrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
// ROLE默认是带ROLE_开头
User user = new User();
user.setUsername(s);
user.setPassword(s);
user.setRoles(list);
return user;
}
}
我们只定义了用户名,密码,角色列表,
其他的账号过期,账号上锁,凭证过期,是否可用都默认设置为true,暂时不考虑。
实际使用的时候是根据username去数据库查询记录,
在根据的userid查询role,
并根据记录设置相关的账号过期,上锁等情况。
3、修改我们的配置类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(getUserDetailService());
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
@Bean
public UserDetailsService getUserDetailService() {
return new MyUserDetailsServiceimp();
}
}
用户密码角色的获取从UserDetailService获取。
4、不拦截的页面
有些页面我们不想拦截,所有人都能访问,这时候只需要修改我们的配置类就行了:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/plugins/**",
"/css/**",
"/fonts/**",
"/js/**",
"/home1",
"/home2"
).permitAll() //默认不拦截静态资源的url pattern (2)
.anyRequest().authenticated().and()
.formLogin()
//.loginPage("/login")// 登录url请求路径 (3)
//.defaultSuccessUrl("/httpapi").permitAll()
.and() // 登录成功跳转路径url(4)
.logout().permitAll();
http.logout().logoutSuccessUrl("/"); // 退出默认跳转页面 (5)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(getUserDetailService());
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
@Bean
public UserDetailsService getUserDetailService() {
return new MyUserDetailsServiceimp();
}
}
如上所示,css,js,font不拦截,/根不拦截,/home1, /home2不拦截
还可以自定义登录页面,以及登录成功之后的跳转页面
我们看一下此时的homecontroller
@RestController
public class HomeController {
@RequestMapping("/")
public String index() {
return "hello index!";
}
@RequestMapping("/home")
public String home() {
return "hello home";
}
@RequestMapping("/home1")
public String home1() {
return "hello home1";
}
@RequestMapping("/home2")
public String home2() {
return "hello home2";
}
}
5、session
spring security默认帮我们管理session,我们改下controller,如下:
@RestController
public class HomeController {
@RequestMapping("/")
public String index() {
return "hello index!";
}
@RequestMapping("/home")
@PreAuthorize("hasRole('ADMIN')")
public String home() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = "";
if (principal instanceof UserDetails) {
username = ((UserDetails)principal).getUsername();
} else {
username = principal.toString();
}
System.out.println(username);
return "hello home";
}
@RequestMapping("/home1")
public String home1() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = "";
if (principal instanceof UserDetails) {
username = ((UserDetails)principal).getUsername();
} else {
username = principal.toString();
}
System.out.println(username);
return "hello home1";
}
}
启动服务,我们一次访问:
http://localhost:8080/home1
http://localhost:8080/home
http://localhost:8080/home1
控制台打印如下:
anonymousUser
zhangsan
zhangsan
springsecurity简单学习的更多相关文章
- Log4j简单学习笔记
log4j结构图: 结构图展现出了log4j的主结构.logger:表示记录器,即数据来源:appender:输出源,即输出方式(如:控制台.文件...)layout:输出布局 Logger机滤器:常 ...
- shiro简单学习的简单总结
权限和我有很大渊源. 培训时候的最后一个项目是OA,权限那块却不知如何入手,最后以不是我写的那个模块应付面试. 最开始的是使用session装载用户登录信息,使用简单权限拦截器做到权限控制,利用资源文 ...
- CentOS 简单学习 firewalld的使用
1. centos7 开始 使用firewalld 代替了 iptables 命令工具为 firewall-cmd 帮助信息非常长,简单放到文末 2. 简单使用 首先开启 httpd 一般都自带安装了 ...
- Windows 下 Docker 的简单学习使用过程之一 dockertoolbox
1. Windows 下面运行 Docker 的两个主要工具1): Docker for Windows2): DockerToolbox区别:Docker For Windows 可以理解为是新一代 ...
- 在MVC中实现和网站不同服务器的批量文件下载以及NPOI下载数据到Excel的简单学习
嘿嘿,我来啦,最近忙啦几天,使用MVC把应该实现的一些功能实现了,说起来做项目,实属感觉蛮好的,即可以学习新的东西,又可以增加自己之前知道的知识的巩固,不得不说是双丰收啊,其实这周来就开始面对下载在挣 ...
- Linux——帮助命令简单学习笔记
Linux帮助命令简单学习笔记: 一: 命令名称:man 命令英文原意:manual 命令所在路径:/usr/bin/man 执行权限:所有用户 语法:man [命令或配置文件] 功能描述:获得帮助信 ...
- OI数学 简单学习笔记
基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. PART1 数论部分 最大公约数 对于正整数x,y,最大的能同时整除它们的数称为最大公约数 常用的:\(lcm(x,y)=xy\ ...
- mongodb,redis简单学习
2.mongodb安装配置简单学习 配置好数据库路径就可以mongo命令执行交互操作了:先将服务器开起来:在开个cmd执行交互操作 ...
- html css的简单学习(三)
html css的简单学习(三) 前端开发工具:Dreamweaver.Hbuilder.WebStorm.Sublime.PhpStorm...=========================== ...
随机推荐
- java代码(7) ---guava之Bimap
guava之Bimap bimap的作用很清晰:它是一个——映射,可以通过key得到value,也可以通过value得到key 一.概述 1.bimap和普通HashMap区别 (1)在java集合类 ...
- HDU - 3591 The trouble of Xiaoqian 题解
题目大意 有 \(N\) 种不同面值的硬币,分别给出每种硬币的面值 \(v_i\) 和数量 \(c_i\).同时,售货员每种硬币数量都是无限的,用来找零. 要买价格为 \(T\) 的商品,求在交易中最 ...
- redis 深入理解redis 主从复制原理
redis 主从复制 master 节点提供数据,也就是写.slave 节点负责读. 不是说master 分支不能读数据,也能只是我们希望将读写进行分离. slave 是不能写数据的,只能处理读请求 ...
- TensorFlow从0到1之TensorFlow优化器(13)
高中数学学过,函数在一阶导数为零的地方达到其最大值和最小值.梯度下降算法基于相同的原理,即调整系数(权重和偏置)使损失函数的梯度下降. 在回归中,使用梯度下降来优化损失函数并获得系数.本节将介绍如何使 ...
- (四)POI-设置单元格的对其方式
原文链接:https://blog.csdn.net/class157/article/details/92817149 package com.java.poi; import org.apache ...
- 从mysql数据库中查询最新的一条数据的方法
第一种方法 SELECT * from a where id = (SELECT max(id) FROM a); 第二种方法: select * FROM 表名 ORDER BY id DESC L ...
- Spring:BeanDefinition&PostProcessor不了解一下吗?
水稻:这两天看了BeanDefinition和BeanFactoryPostProcessor还有BeanPostProcessor的源码.要不要了解一下 菜瓜:six six six,大佬请讲 水稻 ...
- 测试必备工具之最强抓包神器 Charles,你会了么?
前言 作为软件测试工程师,大家在工作中肯定经常会用到各种抓包工具来辅助测试,比如浏览器自带的抓包工具-F12,方便又快捷:比如时下特别流行的Fiddler工具,使用各种web和APP测试的各种场景 ...
- ComplexHeatmap|根据excel表绘制突变景观图(oncoplot)
本文首发于“生信补给站”:https://mp.weixin.qq.com/s/8kz2oKvUQrCR2_HWYXQT4g 如果有maf格式的文件,可以直接oncoplot包绘制瀑布图,有多种展示和 ...
- MongoDB文档(二)--查询
(一)查询文档 查询文档可以使用以下方法 # 以非结构化的方式显示所有的文档 db.<collectionName>.find(document) # 以结构化的方式显示所有文档 db.& ...