一、初识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实现 LeetCode 174 地下城游戏

    174. 地下城游戏 一些恶魔抓住了公主(P)并将她关在了地下城的右下角.地下城是由 M x N 个房间组成的二维网格.我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来 ...

  2. Java实现 LeetCode 106 从中序与后序遍历序列构造二叉树

    106. 从中序与后序遍历序列构造二叉树 根据一棵树的中序遍历与后序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序 ...

  3. Java实现 蓝桥杯 算法训练 1的个数

    试题 算法训练 1的个数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输入正整数n,判断从1到n之中,数字1一共要出现几次.例如1123这个数,则出现了两次1.例如15,那么从1 ...

  4. Android如何使用OKHttp

    首先要在build.gradle里面写入 // 添加OKHttp支持 implementation("com.squareup.okhttp3:okhttp:4.3.1") 下面是 ...

  5. Java实现第十届蓝桥杯质数

    试题 D: 质数 本题总分:10 分 [问题描述] 我们知道第一个质数是 2.第二个质数是 3.第三个质数是 5--请你计算 第 2019 个质数是多少? [答案提交] 这是一道结果填空的题,你只需要 ...

  6. c#发布补丁

    日常开发维护项目中,可能会遇到发布后出现bug,或者忘记改配置文件等等问题,这个时候,可能就需要重新进行下发布,有的开发小伙伴可能会把编译后的代码文件整个替换.这样做虽然也可以实现发布,但是有几个弊端 ...

  7. 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...

  8. zabbix3.2升级3.4报错Database error

    摘要: zabbix3.2版本升级到zabbix3.4版本后打开页面报错,报错内容如下 Database errorThe frontend does not match Zabbix databas ...

  9. 君荣一卡通软件mysql转sqlserver 教程

    Mysql数据库转sql数据库方法 注意:新建的SQL数据库一得先登录一次后再做迁移!!!!特别注意 如果客户以前安装的是mysql数据库,现在希望把mysql数据库转换的sql数据库,方法如下: 1 ...

  10. kali系统安装google拼音

    1.设置多线程下载 /bin/bash -c "$(curl -sL https://git.io/vokNn)" 2.打开终端,输入下面的命令 apt-fast install ...