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实现字符串比较
标题:字符串比较 我们需要一个新的字符串比较函数compare(s1, s2). 对这个函数要求是: 1. 它返回一个整数,表示比较的结果. 2. 结果为正值,则前一个串大,为负值,后一个串大,否则, ...
- Grafana 插件地图Worldmap不显示
介绍 最近上了ELK 日志分析,想着手看下用户的分布情况,在kibana 中展示用户分布情况是没有问题的,但是索引添加到Granfana 中的话就无法展示. 问题描述 添加ES索引以后,map地图一片 ...
- HttpUtil工具类,发送Get/Post请求,支持Http和Https协议
HttpUtil工具类,发送Get/Post请求,支持Http和Https协议 使用用Httpclient封装的HttpUtil工具类,发送Get/Post请求 1. maven引入httpclien ...
- 大话计算机网络一 聊聊UDP
引言 UDP是一个简单的面向数据报的运输层协议 UDP不提供可靠性,它把应用程序传给IP层得数据发送出去,不保证它们能达到目的地 UDP首部 端口号表示发送进程和接受进程. UDP长度字段指的是UDP ...
- MATLAB实例:聚类网络连接图
MATLAB实例:聚类网络连接图 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 本文给出一个简单实例,先生成2维高斯数据,得到数据之后,用模糊C均值( ...
- 【百度前端技术学院 Day5/6】CSS盒模型及Float简单布局
1. 盒模型 1.1 内容区 content 默认情况下,width和height只包括内容区域的宽和高,不包括border.padding.margin使用box-sizing可以使其包含conte ...
- char、short、int、unigned int 之间的类型转换
标准数据类型之间会进行 隐式类型的安全转换 转换规则如下: char→int→unsigned int →long→unsigned long→float→double ↓ sho ...
- Accord.NET重启4.0 开发
Accord.NET Framework是在AForge.NET基础上封装和进一步开发来的.功能也很强大,因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注 ...
- OpenSSH详解
OpenSSH详解(思维导图) 1. SSH概述 SSH 软件架构 认证方式 2. OpenSSH 2.1 客户端程序ssh 配置文件 ssh命令 客户端免密登录 scp sftp 2.2 服务端程序 ...
- Nginx 的变量究竟是怎么一回事?
之前说了很多关于 Nginx 模块的内容,还有一部分非常重要的内容,那就是 Nginx 的变量.变量在 Nginx 中可以说无处不在,认识了解这些变量的作用和原理同样是必要的,下面几乎囊括了关于 Ng ...