1.环境搭建
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-java8timeartifactId>
<version>3.0.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
<version>3.0.11.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
@Controller
public class SerurityController {
@RequestMapping({
"/","/index"})
public String index(){
return "index";
}
@RequestMapping("/login")
public String login(){
return "views/login";
}
@RequestMapping("/view1/{id}")
public String view1(@PathVariable("id") int id){
return "views/view1/"+id;
}
@RequestMapping("/view2/{id}")
public String view2(@PathVariable("id") int id){
return "views/view2/"+id;
}
@RequestMapping("/view3/{id}")
public String view3(@PathVariable("id") int id){
return "views/view3/"+id;
}
}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>首页h1>
<div id="div1" style="background-color: antiquewhite">
<a th:href="@{/view1/1}">view1-1a>
<a th:href="@{/view1/2}">view1-2a>
<a th:href="@{/view1/3}">view1-3a>
div>
<div id="div2" style="background-color: burlywood">
<a th:href="@{/view2/1}">view2-1a>
<a th:href="@{/view2/2}">view2-2a>
<a th:href="@{/view2/3}">view2-3a>
div>
<div id="div3" style="background-color: blueviolet">
<a th:href="@{/view3/1}">view3-1a>
<a th:href="@{/view3/2}">view3-2a>
<a th:href="@{/view3/3}">view3-3a>
div>
<div>
<a th:href="@{/login}">登录a>
<a th:href="@{/logout}">注销a>
div>
body>
html>
2.简介
实现认证授权功能
1.引入启动器(依赖)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
2.编写配置类,实现授权认证功能
package com.cdl.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.bcrypt.BCryptPasswordEncoder;
/**
* date:
* Author:CDL
* desc:
* version:1.0
*/
//底层是Aop横切技术,不用改变越来的代码,就可以实现权限控制
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录也买你
http.formLogin();//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
}
//认证(赋予角色的访问权限)
/**
* 在springboot2.1 以及2.1之前,可以直接使用,2.1之后,会存在很多版本问题,例如:
* 之前可以直接使用明文密码进行登录,现在使用明文密码就会报passwordEncoder错误,意思就是密码需要加密才可以,否则认为不安全的操作
* 在是spring Security5+中,增加了很多密码的加密方式
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
* auth.inMemoryAuthentication() 从内存中那数据进行认证
* auth.jdbcAuthentication() 从数据库拿数据进行仍正
*/
//这些数据正常情况下应该从数据库中读取,此次没有连接数据库,就直接从内存中获取,内存中的读取速度也比较快
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("cdl").password(new BCryptPasswordEncoder().encode("123")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3");
}
}
3.实现注销功能
需要关闭csrf()功能,否者会注销失败,报403错误没有权限,因为登录使用的是get请求,给请求会把用户信息拼接在url后面,不安全,所以springboot默认开启csrf,防止网站被csrf攻击
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录也买你
http.formLogin();//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
//注销并跳转到首页
//http.logout().deleteCookies("remove").invalidateHttpSession(true); 注销并清空所有的session和cookie
http.csrf().disable();//关闭csrf功能,不认可能会出现登出失败
http.logout().logoutSuccessUrl("/");
}
什么是csrf?
以上代码实现的功能是将所有页面展示给所有用户看,对应的用户没有权限使用,现在需要修改代码,不同权限的用户只能看到自己能有权限操作的页面,通过thymeleaf与security结合
1.导入thymeleaf与security的结合包
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-springsecurity4artifactId>
<version>3.0.4.RELEASEversion>
dependency>
2.通过thymeleaf与security的结合标签,sec:authorize,sec:authorize="!isAuthenticated()"等标签实现该功能
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>首页h1>
<div id="div1" style="background-color: antiquewhite" sec:authorize="hasRole('vip1')">
<a th:href="@{/view1/1}">view1-1a>
<a th:href="@{/view1/2}">view1-2a>
<a th:href="@{/view1/3}">view1-3a>
div>
<div id="div2" style="background-color: burlywood" sec:authorize="hasRole('vip2')">
<a th:href="@{/view2/1}">view2-1a>
<a th:href="@{/view2/2}">view2-2a>
<a th:href="@{/view2/3}">view2-3a>
div>
<div id="div3" style="background-color: blueviolet" sec:authorize="hasRole('vip3')">
<a th:href="@{/view3/1}">view3-1a>
<a th:href="@{/view3/2}">view3-2a>
<a th:href="@{/view3/3}">view3-3a>
div>
<div>
<div sec:authorize="!isAuthenticated()">
<a th:href="@{/login}">登录a>
div>
<div sec:authorize="isAuthenticated()">
<a >
用户名:<span sec:authentication="name">span>
a>
div>
<div sec:authorize="isAuthenticated()">
<a th:href="@{/logout}">注销a>
div>
div>
body>
html>
该功能只有在springboot2.0.9及以下才可以实现,在2.0以上会有问题,报错
3.登录页面自定义,不使用security自带的页面,并实现记住我功能
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录页面 跳转到自定义的前端页面loginPage("/Tologin") ,并实现security的功能 loginProcessingUrl("/login"),
// 同时使用usernameParameter("user").passwordParameter("pwd")接受参数
http.formLogin().loginPage("/Tologin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login");//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
//注销并跳转到首页
//http.logout().deleteCookies("remove").invalidateHttpSession(true); 注销并清空所有的session和cookie
http.csrf().disable();//关闭csrf功能,不认可能会出现登出失败
http.logout().logoutSuccessUrl("/");
//开启记住我功能 底层原理:cookie 默认保存时间:14天 自定义记住我,接受前端的参数rememberMeParameter("remenber");需要和前端相匹配
http.rememberMe().rememberMeParameter("remenber");
}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form th:action="@{/login}">
<input name="user">用户名
<input name="pwd">密码
<input name="remember" type="checkbox">记住我
<h1>登录h1>
form>
<a th:href="@{/logout}">注销a>
body>
html>
什么是Shiro
记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可。
Shiro结构
从外部来看Shiro,即从应用程序的角度来看Shiro如何完成工作
Shiro下常用的方法
为什么要做安全
SpringSecurity,shiro:这两个框架很相似,主要做认证,授权(比如V1,V2,V3的功能不一样)功能
权限分类
1.环境搭建
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-java8timeartifactId>
<version>3.0.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
<version>3.0.11.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
@Controller
public class SerurityController {
@RequestMapping({
"/","/index"})
public String index(){
return "index";
}
@RequestMapping("/login")
public String login(){
return "views/login";
}
@RequestMapping("/view1/{id}")
public String view1(@PathVariable("id") int id){
return "views/view1/"+id;
}
@RequestMapping("/view2/{id}")
public String view2(@PathVariable("id") int id){
return "views/view2/"+id;
}
@RequestMapping("/view3/{id}")
public String view3(@PathVariable("id") int id){
return "views/view3/"+id;
}
}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>首页h1>
<div id="div1" style="background-color: antiquewhite">
<a th:href="@{/view1/1}">view1-1a>
<a th:href="@{/view1/2}">view1-2a>
<a th:href="@{/view1/3}">view1-3a>
div>
<div id="div2" style="background-color: burlywood">
<a th:href="@{/view2/1}">view2-1a>
<a th:href="@{/view2/2}">view2-2a>
<a th:href="@{/view2/3}">view2-3a>
div>
<div id="div3" style="background-color: blueviolet">
<a th:href="@{/view3/1}">view3-1a>
<a th:href="@{/view3/2}">view3-2a>
<a th:href="@{/view3/3}">view3-3a>
div>
<div>
<a th:href="@{/login}">登录a>
<a th:href="@{/logout}">注销a>
div>
body>
html>
2.简介
实现认证授权功能
1.引入启动器(依赖)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
2.编写配置类,实现授权认证功能
package com.cdl.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.bcrypt.BCryptPasswordEncoder;
/**
* date:
* Author:CDL
* desc:
* version:1.0
*/
//底层是Aop横切技术,不用改变越来的代码,就可以实现权限控制
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录也买你
http.formLogin();//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
}
//认证(赋予角色的访问权限)
/**
* 在springboot2.1 以及2.1之前,可以直接使用,2.1之后,会存在很多版本问题,例如:
* 之前可以直接使用明文密码进行登录,现在使用明文密码就会报passwordEncoder错误,意思就是密码需要加密才可以,否则认为不安全的操作
* 在是spring Security5+中,增加了很多密码的加密方式
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
* auth.inMemoryAuthentication() 从内存中那数据进行认证
* auth.jdbcAuthentication() 从数据库拿数据进行仍正
*/
//这些数据正常情况下应该从数据库中读取,此次没有连接数据库,就直接从内存中获取,内存中的读取速度也比较快
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("cdl").password(new BCryptPasswordEncoder().encode("123")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3");
}
}
3.实现注销功能
需要关闭csrf()功能,否者会注销失败,报403错误没有权限,因为登录使用的是get请求,给请求会把用户信息拼接在url后面,不安全,所以springboot默认开启csrf,防止网站被csrf攻击
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录也买你
http.formLogin();//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
//注销并跳转到首页
//http.logout().deleteCookies("remove").invalidateHttpSession(true); 注销并清空所有的session和cookie
http.csrf().disable();//关闭csrf功能,不认可能会出现登出失败
http.logout().logoutSuccessUrl("/");
}
什么是csrf?
以上代码实现的功能是将所有页面展示给所有用户看,对应的用户没有权限使用,现在需要修改代码,不同权限的用户只能看到自己能有权限操作的页面,通过thymeleaf与security结合
1.导入thymeleaf与security的结合包
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-springsecurity4artifactId>
<version>3.0.4.RELEASEversion>
dependency>
2.通过thymeleaf与security的结合标签,sec:authorize,sec:authorize="!isAuthenticated()"等标签实现该功能
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>首页h1>
<div id="div1" style="background-color: antiquewhite" sec:authorize="hasRole('vip1')">
<a th:href="@{/view1/1}">view1-1a>
<a th:href="@{/view1/2}">view1-2a>
<a th:href="@{/view1/3}">view1-3a>
div>
<div id="div2" style="background-color: burlywood" sec:authorize="hasRole('vip2')">
<a th:href="@{/view2/1}">view2-1a>
<a th:href="@{/view2/2}">view2-2a>
<a th:href="@{/view2/3}">view2-3a>
div>
<div id="div3" style="background-color: blueviolet" sec:authorize="hasRole('vip3')">
<a th:href="@{/view3/1}">view3-1a>
<a th:href="@{/view3/2}">view3-2a>
<a th:href="@{/view3/3}">view3-3a>
div>
<div>
<div sec:authorize="!isAuthenticated()">
<a th:href="@{/login}">登录a>
div>
<div sec:authorize="isAuthenticated()">
<a >
用户名:<span sec:authentication="name">span>
a>
div>
<div sec:authorize="isAuthenticated()">
<a th:href="@{/logout}">注销a>
div>
div>
body>
html>
该功能只有在springboot2.0.9及以下才可以实现,在2.0以上会有问题,报错
3.登录页面自定义,不使用security自带的页面,并实现记住我功能
@Override
protected void configure(HttpSecurity http) throws Exception {
//HttpSecurity http 属于http安全策略
//首页任何人都可以访问,vip1只能访问view1下的页面,vip2只能访问view2下的页面
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/view1/**").hasRole("vip1")
.antMatchers("/view2/**").hasRole("vip2")
.antMatchers("/view3/**").hasRole("vip3");
//没有权限,会默认跳到登录页面 跳转到自定义的前端页面loginPage("/Tologin") ,并实现security的功能 loginProcessingUrl("/login"),
// 同时使用usernameParameter("user").passwordParameter("pwd")接受参数
http.formLogin().loginPage("/Tologin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login");//不需要定义任何连接去哪里,这句代码会直接定义到登录页面
//注销并跳转到首页
//http.logout().deleteCookies("remove").invalidateHttpSession(true); 注销并清空所有的session和cookie
http.csrf().disable();//关闭csrf功能,不认可能会出现登出失败
http.logout().logoutSuccessUrl("/");
//开启记住我功能 底层原理:cookie 默认保存时间:14天 自定义记住我,接受前端的参数rememberMeParameter("remenber");需要和前端相匹配
http.rememberMe().rememberMeParameter("remenber");
}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form th:action="@{/login}">
<input name="user">用户名
<input name="pwd">密码
<input name="remember" type="checkbox">记住我
<h1>登录h1>
form>
<a th:href="@{/logout}">注销a>
body>
html>
什么是Shiro
记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可。
Shiro结构
从外部来看Shiro,即从应用程序的角度来看Shiro如何完成工作
Shiro下常用的方法