zoukankan      html  css  js  c++  java
  • spring security +MySQL + BCryptPasswordEncoder 单向加密验证 + 权限拦截 --- 心得

    1.前言

    前面学习了 security的登录与登出 , 但是用户信息 是 application 配置 或内存直接注入进去的 ,不具有实用性,实际上的使用还需要权限管理,有些 访问接口需要某些权限才可以使用

    于是多了个权限管理的问题

    2.环境

    spring boot 2.1.6.RELEASE

    mysql 5.5.28*win64

    jdk 1.8.0_221

    3.操作

    (1)准备一张MySQL表

    CREATE TABLE `t_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,自递增',
      `username` varchar(20) DEFAULT NULL COMMENT '用户名',
      `psw` varchar(140) DEFAULT NULL COMMENT '密码',
      `nickname` varchar(50) DEFAULT NULL COMMENT '别名',
      `role` varchar(100) DEFAULT NULL COMMENT '权限名',
      `setTime` datetime DEFAULT NULL COMMENT '注册时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

     

     (2)目录结构

    (3)pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>security-5500</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>security-5500</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <!-- 设置项目编码格式-->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!--spring security 依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--访问静态资源-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!-- MySQL 依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <!--            <scope>runtime</scope>-->
                <version>5.1.30</version>
            </dependency>
            <!--MySQL 数据源 依赖包-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
    
            <!--        mybatis依赖-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.2</version>
            </dependency>
            <!-- mybatis的逆向工程依赖包-->
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-core</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!-- SCryptPasswordEncoder 加密才需要使用-->
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15on</artifactId>
                <version>1.64</version>
            </dependency>
            <!--java工具包-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.9</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    View Code

    (4)配置mybatis 与 dao层接口【具体操作这里不演示,可看我的其他随笔有具体讲解】

     (5)配置前端页面

    index.html

    <!DOCTYPE html>
    <html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
          xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
    </head>
    <body>
    你好 ,世界 ,2333
    <p>点击 <a th:href="@{/home}">我</a> 去home.html页面</p>
    
    </body>
    </html>
    View Code

    home.html

    <!DOCTYPE html>
    <html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
          xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <meta charset="UTF-8">
        <title>security首页</title>
    </head>
    <body>
    <h1>Welcome!你好,世界</h1>
    
    <p>Click <a th:href="@{/hai}">here</a> to see a greeting.</p>
    </body>
    </html>
    View Code

    hai.html

    <!DOCTYPE html>
    <html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
          xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <meta charset="UTF-8">
        <title>hai文件</title>
    </head>
    <body>
        你好呀世界,成功登录进来了
    <br>
    <hr>
    用户名:<span th:text="${username}"></span>
    <hr>
    <!--  登出 路径是在security 拦截规则 那 设置的   ,当然也可以使用自己写的 ,必须post方式才可以访问,因为默认开启了CSRF -->
        <form th:action="@{/mylogout}" method="post">
            <button class="btn btn-danger" style="margin-top: 20px">退出登录</button>
        </form>
    </body>
    </html>
    View Code

    kk.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>kk</title>
    </head>
    <body>
    <img src="img/xx.png" alt="">
    </body>
    </html>
    View Code

    login.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security自定义</title>
    </head>
    <body>
    <div th:if="${param.error}">
        Invalid username and password.
    </div>
    <div th:if="${param.logout}">
        You have been logged out.
    </div>
    <form th:action="@{/login}" method="post">
        <div><label> User Name : <input type="text" name="username"/> </label></div>
        <div><label> Password: <input type="password" name="password"/> </label></div>
        <div><input type="submit" value="Sign In"/></div>
    </form>
    <br>
    lalallalalal啊是德国海
    </body>
    </html>
    View Code

    (6)配置controller 虚拟路径 【访问接口】

    package com.example.security5500.controller;
    
    
    import org.springframework.security.access.annotation.Secured;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.security.core.annotation.AuthenticationPrincipal;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    
    import java.security.Principal;
    
    @Controller
    public class MVCController {
    
        @RequestMapping("/home")
        public String home() {
            return "home";
        }
    
    
        @RequestMapping("/login")
        public String login(){
            return "login";
        }
    
    
        @RequestMapping("/hai")
        public String hai(@AuthenticationPrincipal Principal principal, Model model) {
            //获取登录用户名信息 ,如果没有登录  principal.getName() 会报异常,因此弄个异常抛出
            String  s= "r";
            try {
                if (principal.getName() !=null){
                    s = principal.getName();
                }
            }catch (Exception e){
                System.out.println("principal.getName()出异常");
            }
    
            model.addAttribute("username", s);
            return "hai";
        }
    
        @RequestMapping({"/", "/index"})
        public String index() {
            return "index";
        }
    
        @RequestMapping("kk")
        public String kk() {
            return "kk";
        }
    
    
        //获取用户权限
        @RequestMapping({"/info"})
        @ResponseBody
        public Object info(@AuthenticationPrincipal Principal principal) {
            return principal;
        }
        /*
        {"authorities":[{"authority":"admin"},{"authority":"user"}],
        "details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"1F57B8E39C5D1DB1F875D57D533DB982"},
        "authenticated":true,"principal":{"password":null,"username":"xi","authorities":[{"authority":"admin"},
        {"authority":"user"}],"accountNonExpired":true,"accountNonLocked":true,
        "credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"xi"}
    
         */
    
    
    }
    View Code
    package com.example.security5500.controller;
    
    
    import com.example.security5500.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.annotation.AuthenticationPrincipal;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.security.Principal;
    import java.util.Map;
    
    @Controller
    @RequestMapping("/admin")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
    //    //登出操作
    //    @RequestMapping({"/lo"})
    //    public String logout(HttpServletRequest request, HttpServletResponse response) {
    //        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    //        if (auth != null) {//清除认证
    //            new SecurityContextLogoutHandler().logout(request, response, auth);
    //        }
    //        //重定向到指定页面
    //        return "redirect:/login";
    //    }
    
    
        //添加用户
        @RequestMapping({"/addUser"})
        @ResponseBody
        public Map<String,Object> addUser(String username , String psw ) {
            return userService.addUser(username,psw);
        }
    
    
    }
    View Code

     (7)service层实现类

    package com.example.security5500.service.serviceImpl;
    
    import com.example.security5500.dao.TUserMapper;
    import com.example.security5500.entitis.tables.TUser;
    import com.example.security5500.service.UserService;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Resource
        private TUserMapper tUserMapper;
        
        //根据用户名获取用户信息
        @Override
        public TUser getByUsername(String useranme) {
            return tUserMapper.selectByUsername(useranme);
        }
    
        //添加新用户
        @Override
        public Map<String,Object> addUser(String username, String psw) {
            Map<String,Object> map = new HashMap<>();
            if (StringUtils.isBlank(username) || StringUtils.isBlank(psw))
            {
                map.put("data","参数不可空");
                return map;
            }
    
            ////根据用户名获取用户信息
            TUser u = tUserMapper.selectByUsername(username);
            if (u!= null){
                map.put("data","用户名已经存在");
                return map;
            }
            //
            TUser tUser = new TUser();
            tUser.setUsername(username);
            //
            //BCryptPasswordEncoder 单向加密
            tUser.setPsw((new BCryptPasswordEncoder()).encode(psw));
            //
            tUser.setNickname("别名-昵称");
            tUser.setRole("user");
            tUser.setSettime(new Date());
            int len = tUserMapper.insertSelective(tUser);
            if (len!=1){
                map.put("data","失败");
            }else {
                map.put("data","成功");
            }
            return map;
        }
    }
    View Code

    (8)启动类

    package com.example.security5500;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    
    @SpringBootApplication
    //设置mapper接口包位置
    @MapperScan(basePackages = "com.example.security5500.dao")
    public class Security5500Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Security5500Application.class, args);
        }
    
    
    }
    View Code

    (9)security配置类 ,继承了 WebSecurityConfigurerAdapter  ,重写了父类方法 ,可对访问路径自定义设置拦截规则

    package com.example.security5500.securityConfig;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    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.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.stereotype.Component;
    
    //这个加不加无所谓
    //@Configuration
    //开启security自定义配置
    @EnableWebSecurity
    //开启 Controller层的访问方法权限,与注解@PreAuthorize("hasRole('admin')")配合,但是 经测试,无法使用,前端访问指定接口报错403 ,
    //@EnableGlobalMethodSecurity(prePostEnabled=true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        //实例自定义登录校验接口 【内部有 数据库查询】
        @Autowired
        private DbUserDetailsService dbUserDetailsService;
    
        //拦截规则设置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    //允许基于使用HttpServletRequest限制访问
                    .authorizeRequests()
                    //设置不拦截页面,可直接通过,路径访问 "/", "/index", "/home" 则不拦截,
                    
                    .antMatchers("/", "/index", "/home", "/hhk/**")
                    //是允许所有的意思
                    .permitAll()
                    //访问 /hai 需要admin权限 ,无权限则提示 403
                    .antMatchers("/hai").hasAuthority("admin")
                    //访问 /kk 需要admin或user权限 ,无权限则提示 403
                    .antMatchers("/kk").hasAnyAuthority("admin","user")
                    //路径/admin/**所有的请求都需要admin权限 ,无权限则提示 403
                    .antMatchers("/admin/**").hasAuthority("admin")
                    //其他页面都要拦截,【需要在最后设置这个】
                    .anyRequest().authenticated()
                    .and()
                    //设置自定义登录页面
                    .formLogin()
                    //指定自定义登录页面的访问虚拟路径
                    .loginPage("/login")
                    .permitAll()
                    .and()
    //        添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效
    //        来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
                    .logout()
    //                //指定的登出操作的虚拟路径,需要以post方式请求这个 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用户认证信息达到登出目的
                    .logoutUrl("/mylogout")
                    //登出成功后访问的地址
                    .logoutSuccessUrl("/home");
        }
    
    
        /**
         * 添加 UserDetailsService, 实现自定义登录校验,数据库查询
         */
        @Override
        protected void configure(AuthenticationManagerBuilder builder) throws Exception {
            //注入用户信息,每次登录都会来这查询一次信息,因此不建议每次都向mysql查询,应该使用redis
            //密码加密
            builder.userDetailsService(dbUserDetailsService).passwordEncoder(passwordEncoder());
        }
    
        /**
         * BCryptPasswordEncoder相关知识:
         * 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。
         * 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。
         * BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
         */
        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    
    //    /**
    //     * 选择加密方式 ,密码不加密的时候选择 NoOpPasswordEncoder,不可缺少,否则报错
    //     * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    //     */
    //    @Bean
    //    public static PasswordEncoder passwordEncoder() {
    //        return NoOpPasswordEncoder.getInstance();
    //    }
    
    
    }
    View Code

    (10)实现自定义登录校验,实现了根据用户名去数据库查询用户信息,集齐参数用户名、加密后的密码、权限 , 

    然后使用 new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities); 注册登录用户 ,

    然后内部会自动对比密码 进行校验 【使用 BCryptPasswordEncoder 单项加密】

    package com.example.security5500.securityConfig;
    
    
    import com.example.security5500.entitis.tables.TUser;
    import com.example.security5500.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    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 org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Service
    public class DbUserDetailsService implements UserDetailsService {
    
       @Autowired
       private UserService userService;
    
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //根据用户名查询用户信息
            TUser tUser = userService.getByUsername(username);
            if (tUser == null){
                throw new UsernameNotFoundException("用户不存在!");
            }
            //权限设置
    //        List<GrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
            List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
            String role = tUser.getRole();
            //分割权限名称,如 user,admin
            String[] roles = role.split(",");
            System.out.println("添加权限");
            for (String r :roles){
                System.out.println(r);
                //添加权限
                simpleGrantedAuthorities.add(new SimpleGrantedAuthority(r));
            }
    
    //        simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
            /**
             * 创建一个用于认证的用户对象并返回,包括:用户名,密码,角色
             */
            //输入参数
            return new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities);
        }
    
    }
    View Code

    (11)application.properties

    spring.application.name=security-5500
    # 应用服务web访问端口
    server.port=5500
    #配置security登录账户密和密码  ,不配置则默认账户是user,密码是随机生成的字符串,打印在启动栏中
    #spring.security.user.name=11
    #spring.security.user.password=22
    #
    ##
    ##
    ##
    ## Enable template caching.
    #spring.thymeleaf.cache=true
    ## Check that the templates location exists.
    #spring.thymeleaf.check-template-location=true
    ## Content-Type value.
    ##spring.thymeleaf.content-type=text/html
    ## Enable MVC Thymeleaf view resolution.
    #spring.thymeleaf.enabled=true
    ## Template encoding.
    #spring.thymeleaf.encoding=utf-8
    ## Comma-separated list of view names that should be excluded from resolution.
    #spring.thymeleaf.excluded-view-names=
    ## Template mode to be applied to templates. See also StandardTemplateModeHandlers.
    #spring.thymeleaf.mode=HTML5
    ## Prefix that gets prepended to view names when building a URL.
    ##设置html文件位置
    #spring.thymeleaf.prefix=classpath:/templates/
    ## Suffix that gets appended to view names when building a URL.
    #spring.thymeleaf.suffix=.html  spring.thymeleaf.template-resolver-order=
    # Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.
    #
    #
    #设置mybatis
    #mybatis设置
    #mybatis配置文件所在路径
    mybatis.config-location=classpath:mybatis/config/mybatisConfig.xml
    #所有Entity别名类所在包
    mybatis.type-aliases-package=com.example.security5500.entitis.tables
    #mapper映射xml文件[也可以放在 resources 里面]
    #不论放在哪里,都必须使用classpath: 否则找不到 ,报错 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
    mybatis.mapper-locations= classpath:mybatis/mapper/**/*.xml
    
    
    #mysql配置
    # 当前数据源操作类型
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    # mysql驱动包
    spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver
    # 数据库名称
    spring.datasource.url=jdbc:mysql://localhost:3306/security?characterEncoding=utf-8
    # 数据库账户名
    spring.datasource.username=root
    # 数据库密码
    spring.datasource.password=mysql
    #
    #
    # 数据库连接池的最小维持连接数
    spring.datasource.dbcp2.min-idle=5
    # 初始化连接数
    spring.datasource.dbcp2.initial-size=5
    # 最大连接数
    spring.datasource.dbcp2.max-total=5
    # 等待连接获取的最大超时时间
    spring.datasource.dbcp2.max-wait-millis=200
    #
    # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个,
    #注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
    spring.datasource.druid.test-on-borrow=false
    #
    # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
    #注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
    spring.datasource.druid.test-while-idle=true
    #
    # 指明是否在归还到池中前进行检验,注意: 设置为true后如果要生效,
    #validationQuery参数必须设置为非空字符串
    spring.datasource.druid.test-on-return=false
    #
    # SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.
    #如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录
    spring.datasource.druid.validation-query=select 1
    View Code

     4.测试

     (1)启动 默认进入 index.html

     

     点击 “我” ,进入 home.html

    点击 “here”  ,进入 hai.html ,但是因为设置了拦截,需要登录才可以访问 ,因此进入了自定义的登录页面

    用一个只有 user权限的账户  

    username = cen 

    password = 11

    登录后显示 403

     因为我将访问 hai.html的权限设为需要 admin 才可以访问 ,因此拒绝操作

     换一个有admin权限的账户

    username = xi

    password = 11

    访问网址http://localhost:5500/login

    再次登录

     

     

     这是对一个终端访问接口的权限拦截

    那么,需要将某一路径的请求都给拦截怎么办?难道一个一个写?

    不,可以拦截上一层的虚拟路径

     

     security的的配置写法

     

    (2)一个拦截路径可以设置多个权限,只要有任意一个权限都可以访问

     网址访问 http://localhost:5500/kk  ,【无权限仍然提示403】

     

  • 相关阅读:
    C程序设计课程2012电子信息 第四次上机实验
    C程序设计课程2012电子信息 第一次上机实验
    C程序设计课程2012电子信息第五次上机实验
    软工导论 12132 实验前提条件
    C程序设计课程2012电子信息 第二次上机实验
    C程序设计课程2012电子信息 第三次上机实验
    C程序设计课程2012电子信息 第四堂课后作业
    umbraco中文包应用
    C#遍历一个dictionary
    介绍几款用于单文件或多文件上传的JQuery插件
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13034555.html
Copyright © 2011-2022 走看看