IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> spring Security与thymeleaf与Security的整合 -> 正文阅读

[Java知识库]spring Security与thymeleaf与Security的整合

安全简介

在 Web 开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。如果在应用开发的后期才考虑安全的问题,就可能陷入一个两难的境地:一方面,应用存在严重的安全漏洞,无法满足用户的要求,并可能造成用户的隐私数据被攻击者窃取;另一方面,应用的基本架构已经确定,要修复安全漏洞,可能需要对系统的架构做出比较重大的调整,因而需要更多的开发时间,影响应用的发布进程。因此,从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。

市面上存在比较有名的:Shiro,Spring Security !

?实战测试

1、新建一个初始的springboot项目web模块,thymeleaf模块

2、导入静态资源

?

?3、controller跳转!

????????3.1基于java类配置的试图跳转

@Configuration
public class myConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");


    }


}

? ? ? ? 3.2基于controller跳转 ;两者都一样

@Controller
public class controller {
    @RequestMapping("/tologin")
    public String toLogin(){
        return "login";
    }
@RequestMapping("/leave1/{id}")
    public String leave1(@PathVariable("id") int id){
        return "leave1/"+id;
}
    @RequestMapping("/leave2/{id}")
    public String leave2(@PathVariable("id") int id){
        return "leave2/"+id;
    }
    @RequestMapping("/leave3/{id}")
    public String leave3(@PathVariable("id") int id){
        return "leave3/"+id;
    }
}

测试环境ok!

认识spring Security

?

Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!

记住几个类:

WebSecurityConfigurerAdapter:自定义Security策略

AuthenticationManagerBuilder:自定义认证策略

@EnableWebSecurity:开启WebSecurity模式

Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。

“认证”(Authentication)

身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。

身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。

“授权” (Authorization)

授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。

这个概念是通用的,而不是只在Spring Security 中存在。

认证和授权
目前,我们的测试环境,是谁都可以访问的,我们使用 Spring Security 增加上认证和授权的功能

1、引入 Spring Security 模块

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、编写 Spring Security 配置类

参考官网:https://spring.io/projects/spring-security

查看我们自己项目中的版本,找到对应的帮助文档:

https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5 ? #servlet-applications 8.16.4
3、编写基础配置类 实现WebSecurityConfigurerAdapter接口

@EnableWebSecurity // 开启WebSecurity模式

package com.kuang.config;
 
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;
 
@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
    }
}

?4.定制请求的授权规则

    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //首页所有人可以访问
                .antMatchers("/").permitAll()
                .antMatchers("/index.html").permitAll()
                //设置只有vip1这个角色才能进入这个/leave1/** 下面也是一样的道理
                .antMatchers("/leave1/**").hasRole("vip1")
                .antMatchers("/leave2/**").hasRole("vip2")
                .antMatchers("/leave3/**").hasRole("vip3");

5、测试一下:发现除了首页都进不去了!因为我们目前没有登录的角色,因为请求需要登录的角色拥有对应的权限才可以!

6、在configure()方法中加入以下配置,开启自动配置的登录功能!

// 开启自动配置的登录功能
// /login 请求来到登录页
// /login?error 重定向到这里表示登录失败
http.formLogin();

7、测试一下:发现,没有权限的时候,会跳转到登录的页面!

?8、查看刚才登录页的注释信息;

我们可以定义认证规则,重写configure(AuthenticationManagerBuilder auth)方法

    //认证
    //定制认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //从内存中取数据 这里本来是要从数据库当中取数据的
       
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                .and()
                .withUser("chen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    }
passwordEncoder(new BCryptPasswordEncoder():我们要将前端传过来的密码进行某种方式加密,否则就无法登录;

9、测试,发现,登录成功,并且每个角色只能访问自己认证下的规则!搞定

权限控制和注销

1、开启自动配置的注销的功能

//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
    //....
    //开启自动配置的注销的功能
       // /logout 注销请求
    http.logout();
}

2、我们在前端,增加一个注销的按钮,index.html 导航栏中

<a class="item" th:href="@{/logout}">
    <i class="address card icon"></i> 注销
</a>

3、我们可以去测试一下,登录成功后点击注销,发现注销完毕会跳转到登录页面!

4、但是,我们想让他注销成功后,依旧可以跳转到首页,该怎么处理呢?

//注销之后跳到首页  也可以是/index.html
        http.logout().logoutSuccessUrl("/");

5、测试,注销完毕后,发现跳转到首页OK

6、我们现在又来一个需求:用户没有登录的时候,导航栏上只显示登录按钮,用户登录之后,导航栏可以显示登录的用户信息及注销按钮!还有就是,比如kuangshen这个用户,它只有 vip2,vip3功能,那么登录则只显示这两个功能,而vip1的功能菜单不显示!这个就是真实的网站情况了!该如何做呢?

我们需要结合thymeleaf中的一些功能

sec:authorize="isAuthenticated()":是否认证登录!来显示不同的页面

Maven依赖:

<!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    <version>3.0.4.RELEASE</version>
</dependency>

7、修改我们的 前端页面

导入命名空间

xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"

修改导航栏,增加认证判断

<div th:fragment="topbar" style="width:200px; height: 30px;margin-left:450px ">
    <!--如果未登录-->
    <!--如果权限没有认证-->
    <!--只显示登录按钮-->
    <div sec:authorize="!isAuthenticated()">
        <a class="item" th:href="@{/tologin}">
            <i class="address card icon"></i> 登录
        </a>
    </div>
<!--权限已经认证-->
    <!--没有登录按钮 显示用户名跟注销按钮-->
    <p>
    <div sec:authorize="isAuthenticated()" style="float:right">
        <a class="item">
            <i class="address card icon"></i>
            用户名:<span sec:authentication="name"></span>
        </a>
    </div>

    <div sec:authorize="isAuthenticated()" style="float:right;">
        <a class="item" th:href="@{/logout}">
            <i class="address card icon"></i>注销
        </a>
    </div>
    </p>
    </div>

8、重启测试,我们可以登录试试看,登录成功后确实,显示了我们想要的页面;

9、如果注销404了,就是因为它默认防止csrf跨站请求伪造,因为会产生安全问题,我们可以将请求改为post表单提交,或者在spring security中关闭csrf功能;我们试试:在 配置中增加 http.csrf().disable();

http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
http.logout().logoutSuccessUrl("/");

10、我们继续将下面的角色功能块认证完成!

<div class="div1">
<div class="div"  sec:authorize="hasRole('vip1')">
    <a style="text-decoration: none" th:href="@{/leave1/1}">leave1.1</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave1/2}">leave1.2</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave1/3}">leave1.3</a>
</div>

<div class="div" sec:authorize="hasRole('vip2')">
    <a style="text-decoration: none" th:href="@{/leave2/1}">leave2.1</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave2/2}">leave2.2</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave2/3}">leave2.3</a>
</div>

<div class="div" sec:authorize="hasRole('vip3')">
    <a style="text-decoration: none" th:href="@{/leave3/1}">leave3.1</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave3/2}">leave3.2</a>
    <br>
    <a style="text-decoration: none" th:href="@{/leave3/3}">leave3.3</a>
</div>
</div>

11、测试一下!

12、权限控制和注销搞定

记住我功能实现

现在的情况,我们只要登录之后,关闭浏览器,再登录,就会让我们重新登录,但是很多网站的情况,就是有一个记住密码的功能,这个该如何实现呢?很简单

1、开启记住我功能

//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
    //。。。。。。。。。。。
    //记住我
    http.rememberMe();
}

2、我们再次启动项目测试一下,发现登录页多了一个记住我功能,我们登录之后关闭 浏览器,然后重新打开浏览器访问,发现用户依旧存在!是通过储存cookie来保存用户信息的,我们点击注销的时候,可以发现,spring security 帮我们自动删除了这个 cookie

3.结论:登录成功后,将cookie发送给浏览器保存,以后登录带上这个cookie,只要通过检查就可以免登录了。如果点击注销,则会删除这个cookie,具体的原理在JavaWeb阶段.

定制登录页

现在这个登录页面都是spring security 默认的,怎么样可以使用我们自己写的Login界面呢?

1、在刚才的登录页配置后面指定 loginpage

http.formLogin().loginPage("/tologin");

2、然后前端也需要指向我们自己定义的 login请求

<a class="item" th:href="@{/tologin}">
    <i class="address card icon"></i> 登录
</a>

3.我们登录,需要将这些信息发送到哪里,我们也需要配置,login.html 配置提交请求及方式,方式必须为post:

在 loginPage()源码中的注释上有写明

?

<form th:action="@{/login}" method="post">
    <div class="field">
        <label>Username</label>
        <div class="ui left icon input">
            <input type="text" placeholder="Username" name="username">
            <i class="user icon"></i>
        </div>
    </div>
    <div class="field">
        <label>Password</label>
        <div class="ui left icon input">
            <input type="password" name="password">
            <i class="lock icon"></i>
        </div>
    </div>
    <input type="submit" class="ui blue submit button"/>
</form>

4、这个请求提交上来,我们还需要验证处理,怎么做呢?我们可以查看formLogin()方法的源码!我们配置接收登录的用户名和密码的参数!

http.formLogin()
    .usernameParameter("username")
    .passwordParameter("password")
    .loginPage("/toLogin")
    .loginProcessingUrl("/login"); // 登陆表单提交请求

5、在登录页增加记住我的多选框

<input type="checkbox" name="remember"> 记住我

6、后端验证处理

//定制记住我的参数!
http.rememberMe().rememberMeParameter("remember");

7、测试,OK

完整配置代码

package com.chen.springbootsecurity.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;

@EnableWebSecurity
public class Security extends WebSecurityConfigurerAdapter {
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //首页所有人可以访问
                .antMatchers("/").permitAll()
                .antMatchers("/index.html").permitAll()
                //设置只有vip1这个角色才能进入这个/leave1/** 下面也是一样的道理
                .antMatchers("/leave1/**").hasRole("vip1")
                .antMatchers("/leave2/**").hasRole("vip2")
                .antMatchers("/leave3/**").hasRole("vip3");
        //没有权限就调到登陆界面
        http.formLogin();
        http.logout();
        http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
        //session并发问题 同一个账户登录只能在一个地方登录 如果强行登陆 第一次登录的设备会强制下线
       http.sessionManagement().maximumSessions(1);
        //注销之后跳到首页  也可以是/index.html
        http.logout().logoutSuccessUrl("/");
        //。。。。。。。。。。。
        //记住我
        //定制记住我的参数!
        http.rememberMe().rememberMeParameter("remember");
        //自定义登录页
        http.formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                .loginPage("/tologin")
                .loginProcessingUrl("/login"); // 登陆表单提交请求
    }
    //认证
    //定制认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //从内存中取数据 这里本来是要从数据库当中取数据的

        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                .and()
                .withUser("chen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    }




}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:30:08  更:2021-07-29 11:31:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 17:20:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码