一、初识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简单学习的更多相关文章

  1. Log4j简单学习笔记

    log4j结构图: 结构图展现出了log4j的主结构.logger:表示记录器,即数据来源:appender:输出源,即输出方式(如:控制台.文件...)layout:输出布局 Logger机滤器:常 ...

  2. shiro简单学习的简单总结

    权限和我有很大渊源. 培训时候的最后一个项目是OA,权限那块却不知如何入手,最后以不是我写的那个模块应付面试. 最开始的是使用session装载用户登录信息,使用简单权限拦截器做到权限控制,利用资源文 ...

  3. CentOS 简单学习 firewalld的使用

    1. centos7 开始 使用firewalld 代替了 iptables 命令工具为 firewall-cmd 帮助信息非常长,简单放到文末 2. 简单使用 首先开启 httpd 一般都自带安装了 ...

  4. Windows 下 Docker 的简单学习使用过程之一 dockertoolbox

    1. Windows 下面运行 Docker 的两个主要工具1): Docker for Windows2): DockerToolbox区别:Docker For Windows 可以理解为是新一代 ...

  5. 在MVC中实现和网站不同服务器的批量文件下载以及NPOI下载数据到Excel的简单学习

    嘿嘿,我来啦,最近忙啦几天,使用MVC把应该实现的一些功能实现了,说起来做项目,实属感觉蛮好的,即可以学习新的东西,又可以增加自己之前知道的知识的巩固,不得不说是双丰收啊,其实这周来就开始面对下载在挣 ...

  6. Linux——帮助命令简单学习笔记

    Linux帮助命令简单学习笔记: 一: 命令名称:man 命令英文原意:manual 命令所在路径:/usr/bin/man 执行权限:所有用户 语法:man [命令或配置文件] 功能描述:获得帮助信 ...

  7. OI数学 简单学习笔记

    基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. PART1 数论部分 最大公约数 对于正整数x,y,最大的能同时整除它们的数称为最大公约数 常用的:\(lcm(x,y)=xy\ ...

  8. mongodb,redis简单学习

     2.mongodb安装配置简单学习                   配置好数据库路径就可以mongo命令执行交互操作了:先将服务器开起来:在开个cmd执行交互操作                 ...

  9. html css的简单学习(三)

    html css的简单学习(三) 前端开发工具:Dreamweaver.Hbuilder.WebStorm.Sublime.PhpStorm...=========================== ...

随机推荐

  1. java实现字符串比较

    标题:字符串比较 我们需要一个新的字符串比较函数compare(s1, s2). 对这个函数要求是: 1. 它返回一个整数,表示比较的结果. 2. 结果为正值,则前一个串大,为负值,后一个串大,否则, ...

  2. Grafana 插件地图Worldmap不显示

    介绍 最近上了ELK 日志分析,想着手看下用户的分布情况,在kibana 中展示用户分布情况是没有问题的,但是索引添加到Granfana 中的话就无法展示. 问题描述 添加ES索引以后,map地图一片 ...

  3. HttpUtil工具类,发送Get/Post请求,支持Http和Https协议

    HttpUtil工具类,发送Get/Post请求,支持Http和Https协议 使用用Httpclient封装的HttpUtil工具类,发送Get/Post请求 1. maven引入httpclien ...

  4. 大话计算机网络一 聊聊UDP

    引言 UDP是一个简单的面向数据报的运输层协议 UDP不提供可靠性,它把应用程序传给IP层得数据发送出去,不保证它们能达到目的地 UDP首部 端口号表示发送进程和接受进程. UDP长度字段指的是UDP ...

  5. MATLAB实例:聚类网络连接图

    MATLAB实例:聚类网络连接图 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 本文给出一个简单实例,先生成2维高斯数据,得到数据之后,用模糊C均值( ...

  6. 【百度前端技术学院 Day5/6】CSS盒模型及Float简单布局

    1. 盒模型 1.1 内容区 content 默认情况下,width和height只包括内容区域的宽和高,不包括border.padding.margin使用box-sizing可以使其包含conte ...

  7. char、short、int、unigned int 之间的类型转换

    标准数据类型之间会进行 隐式类型的安全转换 转换规则如下: char→int→unsigned int →long→unsigned long→float→double ↓           sho ...

  8. Accord.NET重启4.0 开发

    Accord.NET Framework是在AForge.NET基础上封装和进一步开发来的.功能也很强大,因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注 ...

  9. OpenSSH详解

    OpenSSH详解(思维导图) 1. SSH概述 SSH 软件架构 认证方式 2. OpenSSH 2.1 客户端程序ssh 配置文件 ssh命令 客户端免密登录 scp sftp 2.2 服务端程序 ...

  10. Nginx 的变量究竟是怎么一回事?

    之前说了很多关于 Nginx 模块的内容,还有一部分非常重要的内容,那就是 Nginx 的变量.变量在 Nginx 中可以说无处不在,认识了解这些变量的作用和原理同样是必要的,下面几乎囊括了关于 Ng ...