org.springframework.boot spring-boot-starter-security org.thymeleaf.extras thymeleaf-extras-springsecurity5
@Controller
public class RouterController {
@RequestMapping({"/", "/index"})
public String toIndex() {
return "index";
}
@RequestMapping("/toLogin")
public String toLogin() {
return "views/login";
}
@RequestMapping("/level1/{id}")
public String level1(@PathVariable("id") Integer id) {
return "views/level1/" + id;
}
@RequestMapping("/level2/{id}")
public String level2(@PathVariable("id") Integer id) {
return "views/level2/" + id;
}
@RequestMapping("/level3/{id}")
public String level3(@PathVariable("id") Integer id) {
return "views/level3/" + id;
}
}
1、启动项目在控制台会打印如下信息
此时在浏览器输入http://localhost:8001,会跳转到登录页面:
默认用户名为user,密码就是控制台打印的。
以上信息说明SpringSecurity生效了!正确输入上面的用户和密码即可登陆将进入首页!
点击到达SpringSecurity学习文档
授权操作
@Override
protected void configure(HttpSecurity http) throws Exception {
//授权
//首页所有的人都可以访问,功能页只有对应有权限的人才可以访问
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
}
登陆ip地址http://localhost:8001即可直接成功访问首页
随便点击一个链接,出现禁止访问的提示!
在配置类中的方法protected void configure(HttpSecurity http) throws Exception添加“如果没有权限访问就到登陆页面” 这个登陆页面是SpringSecurity自定义的
//没有权限默认会到登陆页面
http.formLogin();
在配置类中添加认证操作的方法protected void configure(AuthenticationManagerBuilder auth) throws Exception
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常是从数据库中读出的
//从内存中认证,也可以从数据库中查询相应角色的数据进行认证
auth.inMemoryAuthentication()
.withUser("ml").password("123456").roles("vip1","vip2")
.and()
.withUser("root").password("123").roles("vip1","vip2","vip3")
.and()
.withUser("guest").password("1").roles("vip1");
}
登陆iphttp://localhost:8001/访问首页,点击level1下的链接,使用
登陆
出现下面的错误!
解决方法,修改上面的配置类(原因是SpringSecurity认为使用.withUser("ml").password("123456").roles("vip1","vip2")。设置密码太简单,如果使用反编译,密码是极为不方便的。所以将明文加密防止反编译)
配置类修改如下
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常是从数据库中读出的
//从内存中认证,也可以从数据库中查询相应角色的数据进行认证
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("ml").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("12")).roles("vip1");
}
重启项目,使用下面的账号、密码登陆测试!
可以看到使用ml、123456登陆可以访问vip1和vip2下的.antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2")
但是使用ml、123456登陆却不可以访问 .antMatchers("/level3/**").hasRole("vip3")
//开启注销功能,跳到到首页
http.logout();
上面的toLogin是@Controller中请求的路径(请求登陆),而logout不是我们自己写的@Controller中的请求,是根据http.logout点击进去的源码得来的,说明源码中已经给我们定义好了注销功能的路径,不用我们再自己写
即可使用该密码、账号访问对应的页面!
点击右上角的“注销”功能!
点击退出到登陆页面
当然也可以直接使用我们自己定义好的路由直接退出到首页。修改上面的视图(这个是错误的,上面是正确的的。原因在下面)
这样即使点击“注销”,但是事实上并没有注销,即使退回到首页,但是我们还可以再次点击访问但是可以不通过账号、密码就可以访问刚才的页面。所以这样的做法是不科学的!所以前面的操作才是正确的
继续正确的操作(注销后再次访问刚才已经访问过的密码必须使用账号、密码),继续修改使
//开启注销功能,跳到到首页
http.logout().logoutSuccessUrl("/");
这样就可以做到即使注销也可以直接退出到首页,并且保证再次访问与刚才一样的页面也必须是使用账号、密码登陆才可以,保护了数据的安全!这也就是为什么不能使用上面的那种方式,直接在页面添加路由跳转到首页的原因!
(2)、权限控制(根据不同的用户显示不同的版块)不仅需要security包还需要thymeleafSpringsecurity包进行整合!
org.springframework.boot spring-boot-starter-security org.thymeleaf.extras thymeleaf-extras-springsecurity5
在index.html页面中添加xmlns:sec="http://www.thymeleaf.org/extras/spring-security"命名空间会出现themleaf和springSecurity的整合代码提示"
使用ip http://localhost:8001/登陆首页如下,只有“登陆”字样,没有“用户名和注销”
随便点击一个,使用对应拥有权限的的密码和账户登陆,我选择auth.inMemoryAuthentication() .withUser("ml").password("123456").roles("vip1","vip2"),登陆如下
点击登陆之后可以看到有对应的“用户名和注销操作”
点击“注销操作”之后可以看到没有了对应权限操作的“用户名和注销操作”
但是以上还存在的问题是在没有任何相应权限的用户登陆的时候,应该在首页什么都不显示;而在登陆之后应该显示其具有权限操作的版块
这样在没有任何相应权限的用户登陆的时候,应该在首页什么都不显示
但是使用账号、密码登陆ip http://localhost:8001/login之后可以看见显示具有相应权限的版块! .antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3"); .withUser("ml").password("123456").roles("vip1","vip2") .and() .withUser("root").password("123").roles("vip1","vip2","vip3") .and() .withUser("guest").password("1").roles("vip1");
这样可以直接点击访问想要的操作!
同理使用 .withUser("root").password("123").roles("vip1","vip2","vip3")登陆可以看见所有权限的版块
至此“权限控制操作”到此结束!
5、记住我以及首页定制
(1)、记住我
在配置类中的protected void configure(HttpSecurity http) throws Exception方法中添加
//防止网站工具:get、post
http.csrf().disable(); //关闭csrf功能,登陆失败可能存在的原因
http.logout().logoutSuccessUrl("/");
//开启记住我的功能 cookie,默认保存两天
http.rememberMe();
使用 http.rememberMe();就开启了记住我功能
可以与之前的登陆页面比较一下“记住我”功能就有了!
然后关掉浏览器,再次使用iphttp://localhost:8001/访问,可以发现不用账号、密码可以直接访问之前访问过的页面,这就是记住我的功能的实现!
可以发现“记住我的功能”是通过cookie实现的,时间是两周
所以要是清除掉cookie,那么“记住我的功能”就会失效!
(2)、首页定制(登陆页面)因为之前演示的操作都是使用springSecurity中已经写好的登陆页面
要使用我们自己定义好的只需要在在配置类中的protected void configure(HttpSecurity http) throws Exception方法中修改
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().loginPage("/toLogin");
所以使用我们自己定义好的登陆页面,没有了“记住我的功能”
但是登陆失败,可以看到路由,我们没有这个请求路径http://localhost:8001/usr/login
将login.html中的跳转路由修改如下(修改前)
login.html中的跳转路由修改修改后
再次登陆测试
成功!
当然也可以这样修改!login.html中的登陆请求依然使用springSecurity规定的请求路径“/login”,而不是使用上面我们自己定义好的“toLogin”,并且在配置类中的方法 protected void configure(HttpSecurity http) throws Exception中添加修改如下
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");
这样也可以访问成功!
这样也会出现各种问题:因为在我们自己定义好的login.html中登陆请求的是 和 ,而按照 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");虽然走的是“/toLogin”但是还是走的是springSecurity默认的路径参数规定。此时必须保证formLogin中的username、password和前端中的username、password相同,否则还是登陆不了
在配置类中做出如下修改:
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");
这样即使前端中的name属性中的值和人家底层默认的不一样,我们还是可以在这里修改与前端中的一样保证不出错!
所以两种方式定义首页
第一种
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().loginPage("/toLogin");
index.html页面跳转到登陆页面
login.html页面登陆
第二种
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");
当然在定制首页中再加一个“记住我的功能”
//开启记住我的功能 cookie
http.rememberMe().rememberMeParameter("remember");
首页定制成功!
6、上面用到的java配置类
package com.ml.springSecurity.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;
//Aop横切的方式
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//授权
//首页所有的人都可以访问,功能页只有对应有权限的人才可以访问
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");
//开启注销功能,跳到到首页
//防止网站工具:get、post
http.csrf().disable(); //关闭csrf功能,登陆失败可能存在的原因
http.logout().logoutSuccessUrl("/");
//开启记住我的功能 cookie
http.rememberMe().rememberMeParameter("remember");
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常是从数据库中读出的
//从内存中认证,也可以从数据库中查询相应角色的数据进行认证
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("ml").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("12")).roles("vip1");
}
}
Java相关栏目本月热门文章
- 1【Linux驱动开发】设备树详解(二)设备树语法详解
- 2别跟客户扯细节
- 3Springboot+RabbitMQ+ACK机制(生产方确认(全局、局部)、消费方确认)、知识盲区
- 4【Java】对象处理流(ObjectOutputStream和ObjectInputStream)
- 5【分页】常见两种SpringBoot项目中分页技巧
- 6一文带你搞懂OAuth2.0
- 7我要写整个中文互联网界最牛逼的JVM系列教程 | 「JVM与Java体系架构」章节:虚拟机与Java虚拟机介绍
- 8【Spring Cloud】新闻头条微服务项目:FreeMarker模板引擎实现文章静态页面生成
- 9JavaSE - 封装、static成员和内部类
- 10树莓派mjpg-streamer实现监控及拍照功能调试
- 11用c++写一个蓝屏代码
- 12从JDK8源码中看ArrayList和LinkedList的区别
- 13idea 1、报错java: 找不到符号 符号: 变量 log 2、转换成Maven项目
- 14在openwrt使用C语言增加ubus接口(包含C uci操作)
- 15Spring 解决循环依赖
- 16SpringMVC——基于MVC架构的Spring框架
- 17Andy‘s First Dictionary C++ STL set应用
- 18动态内存管理
- 19我的创作纪念日
- 20Docker自定义镜像-Dockerfile



