14.SpringSecurity入门到精通

SpringSecurity(安全)

  • 为什么要做安全
    • 在web开发中,安全第一位,过滤器,拦截器等
    • 他不是一个功能性需求,做网站,安全什么时候去考虑?如果不考虑安全,就会有漏洞,用户隐式泄露等问题,假设架构一旦确定,在去考虑安全问题,将会改动大量代码,所以安全问题,应该在设计之初就考虑
    • 当使用拦截器,过滤器解决这些问题,会使用大量的原生代码以及冗余
  • 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.简介

  • Spring Security是针对Spring项目的安全框架,也是spring boot底层安全模块默认的技术选型,它可以实现强大的web安全控制,对于安全控制,我们只需要引入spring-boot-starter-secyrity模块,进行少量配置,即可实现强大的安全管理功能
  • 记住这几个类
    • WebSecurityConfigurerAdapter:自定义Serurity策略
    • AuthenticationManagerBuilder:自定义认证策略
    • @EnableWebSecurity:开启WenSecurity模式
  • Spring Saecurity的两个主要目标是“认证”和“授权”(访问控制)
    • “认证”(Authentication)
    • “授权”(Authorization)
    • 这两个概念是通用的,而不是只在Spring Security
  • 参考官网:https://spring.io/projects/spring-security
  • 根据版本对应的帮助文档:https://docs.spring.io/spring-security/site/docs/5.2.8.BUILD-SNAPSHOT/reference/htmlsingle/

实现认证授权功能

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

    • Apache Shiro是一个java的安全(权限)框架
    • Shiro可以非常容易的开发出足够好的应用,其不仅可以在JavaSE环境,也可以用在JavaEE环境
    • Shiro可以完成认证,授权,加密,会话管理,Web集成,缓存等
    • 官方网站:https://shiro.apache.org/
  • 有哪些功能?
    14.SpringSecurity入门到精通_第1张图片

    • Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
    • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    • Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
    • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    • Web Support:Web 支持,可以非常容易的集成到 Web 环境;
    • Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
    • Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    • Testing:提供测试支持;
    • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
  • 记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可。

  • Shiro结构

  • 从外部来看Shiro,即从应用程序的角度来看Shiro如何完成工作
    14.SpringSecurity入门到精通_第2张图片

    • subject:应用代码直接交互的对象是Subjiect,也就是说Shiro对外交互的核心Api就是Subject,Subject代表了当前用户,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager,Subject其实是一个门面,SecurityManager才是实际的执行者
    • SecurityManager:安全管理器,即所有与安全的操作都会与SecurityManager有关,并且他管理着所有的Subject,可以看出他是shiro的核心,他负责与shiro的其他组件交互,相当于SpringMVC的DispatcherServlet的角色
    • Realm:Shiro是从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager要验证用户的身份,那么他需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法,也需要从Realm得到用户相应的角色,权限,进行验证用户的操作是否能够进行,可以把Relam看成DataSource
  • 从内部来看Shiro的结构
    14.SpringSecurity入门到精通_第3张图片

    • Subject:任何可以与应用交互的"用户"
    • Security Manager:相当于SpringMvc的DispatcherServlet,是shiro的心脏,所有具体的交互都通过Security Manager进行控制,他管理着所有的Subject,切负责认证,授权,会话以及缓存管理
    • Authenticator:负责Subject的认证,是一个扩展点,可以自定义实现,可以使用认证策略(Authencitation Strategy),即实现什么情况下算用户认证通过了
    • Authorizer:授权期,即访问控制器,用来决定主体是否有权限进行相应的操作,即控制着用户能访问相应的哪些功能
    • Realm:可以有一个或者多个Relam,可以认为是安全实体数据源,及用于获取安全实体,可以用JDBC实现,也可以是内存实现等等,由用户提供,所以一般都是自己实现Relam
    • SessionManager:管理session的生命周期组件,而Shiro并不仅仅可以用在web中,还可以用在javaSE环境中
    • CacheManager:缓存控制器,来管理用户,角色,权限的缓存,因为这些数据基本很少改变,放在缓存中可以提高访问的性能
    • Cryptography:密码模块,Shiro提供一些常用的密码组件用于密码加密解密等等
  • Shiro下常用的方法

    • SecurityUtils.getSubject(); 获取当前用户对象
    • currentUser.getSession(); 通过当前用户拿到session(该session不是http的session,是shiro的session)
    • currentUser.isAuthenticated();判断当前用户是否被认证
    • currentUser.getPrincipal(); 获得当前用户的认证
    • currentUser.hasRole(“schwartz”);获取该用户是否用什么什么角色
    • currentUser.isPermitted(“lightsaber:wield”) 获得当前用户的权限
    • currentUser.logout(); 注销# SpringSecurity(安全)
  • 为什么要做安全

    • 在web开发中,安全第一位,过滤器,拦截器等
    • 他不是一个功能性需求,做网站,安全什么时候去考虑?如果不考虑安全,就会有漏洞,用户隐式泄露等问题,假设架构一旦确定,在去考虑安全问题,将会改动大量代码,所以安全问题,应该在设计之初就考虑
    • 当使用拦截器,过滤器解决这些问题,会使用大量的原生代码以及冗余
  • 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.简介

  • Spring Security是针对Spring项目的安全框架,也是spring boot底层安全模块默认的技术选型,它可以实现强大的web安全控制,对于安全控制,我们只需要引入spring-boot-starter-secyrity模块,进行少量配置,即可实现强大的安全管理功能
  • 记住这几个类
    • WebSecurityConfigurerAdapter:自定义Serurity策略
    • AuthenticationManagerBuilder:自定义认证策略
    • @EnableWebSecurity:开启WenSecurity模式
  • Spring Saecurity的两个主要目标是“认证”和“授权”(访问控制)
    • “认证”(Authentication)
    • “授权”(Authorization)
    • 这两个概念是通用的,而不是只在Spring Security
  • 参考官网:https://spring.io/projects/spring-security
  • 根据版本对应的帮助文档:https://docs.spring.io/spring-security/site/docs/5.2.8.BUILD-SNAPSHOT/reference/htmlsingle/

实现认证授权功能

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

    • Apache Shiro是一个java的安全(权限)框架
    • Shiro可以非常容易的开发出足够好的应用,其不仅可以在JavaSE环境,也可以用在JavaEE环境
    • Shiro可以完成认证,授权,加密,会话管理,Web集成,缓存等
    • 官方网站:https://shiro.apache.org/
  • 有哪些功能?
    14.SpringSecurity入门到精通_第4张图片

    • Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
    • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    • Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
    • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    • Web Support:Web 支持,可以非常容易的集成到 Web 环境;
    • Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
    • Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    • Testing:提供测试支持;
    • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
  • 记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可。

  • Shiro结构

  • 从外部来看Shiro,即从应用程序的角度来看Shiro如何完成工作
    14.SpringSecurity入门到精通_第5张图片

    • subject:应用代码直接交互的对象是Subjiect,也就是说Shiro对外交互的核心Api就是Subject,Subject代表了当前用户,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager,Subject其实是一个门面,SecurityManager才是实际的执行者
    • SecurityManager:安全管理器,即所有与安全的操作都会与SecurityManager有关,并且他管理着所有的Subject,可以看出他是shiro的核心,他负责与shiro的其他组件交互,相当于SpringMVC的DispatcherServlet的角色
    • Realm:Shiro是从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager要验证用户的身份,那么他需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法,也需要从Realm得到用户相应的角色,权限,进行验证用户的操作是否能够进行,可以把Relam看成DataSource
  • 从内部来看Shiro的结构
    14.SpringSecurity入门到精通_第6张图片

    • Subject:任何可以与应用交互的"用户"
    • Security Manager:相当于SpringMvc的DispatcherServlet,是shiro的心脏,所有具体的交互都通过Security Manager进行控制,他管理着所有的Subject,切负责认证,授权,会话以及缓存管理
    • Authenticator:负责Subject的认证,是一个扩展点,可以自定义实现,可以使用认证策略(Authencitation Strategy),即实现什么情况下算用户认证通过了
    • Authorizer:授权期,即访问控制器,用来决定主体是否有权限进行相应的操作,即控制着用户能访问相应的哪些功能
    • Realm:可以有一个或者多个Relam,可以认为是安全实体数据源,及用于获取安全实体,可以用JDBC实现,也可以是内存实现等等,由用户提供,所以一般都是自己实现Relam
    • SessionManager:管理session的生命周期组件,而Shiro并不仅仅可以用在web中,还可以用在javaSE环境中
    • CacheManager:缓存控制器,来管理用户,角色,权限的缓存,因为这些数据基本很少改变,放在缓存中可以提高访问的性能
    • Cryptography:密码模块,Shiro提供一些常用的密码组件用于密码加密解密等等
  • Shiro下常用的方法

    • SecurityUtils.getSubject(); 获取当前用户对象
    • currentUser.getSession(); 通过当前用户拿到session(该session不是http的session,是shiro的session)
    • currentUser.isAuthenticated();判断当前用户是否被认证
    • currentUser.getPrincipal(); 获得当前用户的认证
    • currentUser.hasRole(“schwartz”);获取该用户是否用什么什么角色
    • currentUser.isPermitted(“lightsaber:wield”) 获得当前用户的权限
    • currentUser.logout(); 注销

你可能感兴趣的:(技术文档,java,spring)