SpringSecurity入门和与SpringBoot整合使用

SpringSecurity

官方文档

https://spring.io/projects/spring-security

一. SpringSecurity 简介

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。

Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求

  spring security 的核心功能主要包括:

  • 认证 (你是谁)
  • 授权 (你能干什么)
  • 攻击防护 (防止伪造身份)

二.SpringSecurity 案例

1. 创建一个springboot 项目  (没有加入SpringSecurity的包)

写一个controller类 

@RestController

public class TestController {

    @GetMapping("/hello")

    public String hello(){

        return "hello !";

    }

}

测试发现:

当我们在浏览器访问http://localhost:8080/hello的时候可以在浏览器看到hello!

2. 项目中导入SpringSecurity的依赖

   <!--    父依赖 -->

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.3.4.RELEASE</version>

        <relativePath/>

    </parent>

 <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-security</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.projectlombok</groupId>

            <artifactId>lombok</artifactId>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.springframework.security</groupId>

            <artifactId>spring-security-test</artifactId>

            <scope>test</scope>

        </dependency>

 </dependencies>

再次访问http://localhost:8080/hello 发现  会自动跳转到Spring Security 自带的一个登录页面

说明Spring Security 已经起作用了,我们需要登陆才能访问。

右键点击查看源代码:

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <meta name="description" content="">

    <meta name="author" content="">

    <title>Please sign in</title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">

    <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>

  </head>

  <body>

     <div class="container">

      <form class="form-signin" method="post" action="/login">

        <h2 class="form-signin-heading">Please sign in</h2>

        <p>

          <label for="username" class="sr-only">Username</label>

          <input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>

        </p>

        <p>

          <label for="password" class="sr-only">Password</label>

          <input type="password" id="password" name="password" class="form-control" placeholder="Password" required>

        </p>

<input name="_csrf" type="hidden" value="b6c58934-d11a-4346-8955-27e9f90ec952" />

        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>

      </form>

</div>

</body>

</html>

上面的html中有个form ,其中action="/login",这个/login依然是spring security提供的。form表单提交了三个数据:

username 用户名

password 密码 

_csrf CSRF保护方面的内容,暂时先不展开解释  CSRF  跨站请求伪造

3. 用户名配置

默认情况下,登录的用户名是 user,密码则是项目启动时随机生成的字符串,可以从启动的控制台日志中看到默认密码:

我们在登录页面输入user和密码8fa79a36-8701-4419-826f-cb21a1fa9dd5。可以登录成功,并能访问/hello的内容。

这个随机生成的密码,每次启动时都会变。对登录的用户名/密码进行配置,有三种不同的方式:

  • 在 application.yml 中进行配置
  • 通过 Java 代码配置在内存中
  • 通过 Java 从数据库中加载

配置文件配置用户名/密码

spring:

  security:

    user:

      name:  admin

      password:  123456

   

4. 自定义security配置

上面我们看到默认情况下,spring为我们提供了一个「httpBasic」模式的简单登陆页面,并在控制台输出了密码(这个密码每次启动都是不一样的)。如果我们想用自己的定义的账号密码,则需要改配置。也就是 Java 代码中配置用户名密码 。

下:

新建一个class :MySecurityConfig

@Configuration

@EnableWebSecurity  // 开启WebSecurity模式

public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    //链式编程

    // 授权

    @Override

    protected void configure(HttpSecurity http) throws Exception {

       http.authorizeRequests()//对所有请求进行授权

                .antMatchers("/test/**")

                .permitAll()//放行,允许访问

                .antMatchers("/user/**").hasRole("root")

                .antMatchers("/product/**").hasRole("hjj")

                .anyRequest() //其他未设置的全部请求

                .authenticated() //需要认证

                .and()

                .formLogin() //设置未授权请求跳转到登录页面:开启表单登录功能

//.loginPage("/index.jsp") //指定登录页

                .permitAll() //为登录页设置所有人都可以访问

                .defaultSuccessUrl("/test/info"); //设置登录成功后默认前往的 URL 地址

    }

//    认证

    @Override

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth

            .inMemoryAuthentication()

            .withUser("admin")

            .password("123456").roles("root","hjj")

            .and()

            .withUser("cw")

            .password("111111").roles("root")

            .and()

            .withUser("yyqx")

             .password("222222").roles("hjj");

    }

}

记住几个类:

WebSecurityConfigurerAdapter:自定义Security策略

AuthenticationManagerBuilder:自定义认证策略

@EnableWebSecurity:开启WebSecurity模式

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

测试,我们可以使用这些账号登录进行测试!发现会报错!

There is no PasswordEncoder mapped for the id “null”

原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录

//   认证

    @Override

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth

            .inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())

            .withUser("admin")

            .password(new BCryptPasswordEncoder().encode("123456")).roles("root","hjj")

            .and()

            .withUser("cw")

            .password(new BCryptPasswordEncoder().encode("111111")).roles("root")

            .and()

            .withUser("yyqx")

            .password(new BCryptPasswordEncoder().encode("222222")).roles("hjj");

    }

5.  角色 访问 资源

@RestController

@RequestMapping("/test")

public class TestController {

    @GetMapping("/info")

    public String info(){

        return "test info!";

    }

}


@RestController

@RequestMapping("/product")

public class ProductController {

    @GetMapping("/info")

    public String info(){

        return "product info!";

    }

}


@RestController

@RequestMapping("/user")

public class UserController {

    @GetMapping("/hello")

    public String hello(){

        return "hello user!";

    }

}

如果登录的时候是用 admin 登录 发现是都可以访问的,因为它有 root和hjj 这两个权限

但如果是用cw ,  他只有root 的权限 只能访问 /user/** 下面的,不能访问 /product/** 下面的

同理 可知 用 yyqx  登录的,他只有 hjj 的权限,所以不能访问 /user/**  下面的

7.  自定义登录页面

7.1导入依赖

  <dependency>

            <groupId>org.thymeleaf.extras</groupId>

            <artifactId>thymeleaf-extras-springsecurity5</artifactId>

  </dependency>

7.2 写页面

   1. 导入命名空间

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

    2.  写首页

    index.html

<div>

    <!--如果未登录-->

    <div sec:authorize="!isAuthenticated()">

        <a  th:href="@{/test/login}">

           登录

        </a>

    </div>

    <!--如果已登录-->

    <div sec:authorize="isAuthenticated()">

        <a >

            用户名:<span sec:authentication="principal.username"></span>

            角色:<span sec:authentication="principal.authorities"></span>

        </a>

    </div>

    <div sec:authorize="isAuthenticated()">

        <a th:href="@{/logout}">

           注销

        </a>

    </div>

</div>

 login.html

<form th:action="@{/login}" method="post">

    <div>

       用户名:  <input type="text" placeholder="请输入用户名" name="username"/>

     </div>

    <div >

       密码: <input type="password" placeholder="请输入密码" name="password"/>

    </div>

    <div >

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

    </div >

    <input type="submit" class="ui blue submit button"/>

</form>

3. 定制请求的授权规则

修改代码

    //链式编程

    // 授权

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()//对所有请求进行授权

                .antMatchers("/test/**")

                .permitAll()//放行,允许访问

                .antMatchers("/user/**").hasRole("root")

                .antMatchers("/product/**").hasRole("hjj")

                .anyRequest() //其他未设置的全部请求

                .authenticated() //需要认证

                .and()

                .formLogin() //设置未授权请求跳转到登录页面:开启表单登录功能

  //自定义页面中 有默认的name:username和password 如果不是这两个会报错

        //所以 name 和 password 属性也可以自定义

//                .usernameParameter("username")

//                .passwordParameter("password")

                .loginPage("/test/login") //自定义 登录页

                .loginProcessingUrl("/login")// 登陆表单提交请求

                .defaultSuccessUrl("/")   //设置登录成功后默认前往的 URL 地址

                .and()

                .logout();

//                .logoutUrl("/logout")  //自定义 注销 页

//                .logoutSuccessUrl("/");   //注销成功后 跳转到的页面

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

    }

还可以开启记住我 功能

页面:

 <div >

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

 </div >

后端:

//定制记住我的参数!

http.rememberMe().rememberMeParameter("remember");

三.SpringSecurity 案例2(数据库)

1.数据库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis-role` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `mybatis-role`;

/*Table structure for table `t_role` */

DROP TABLE IF EXISTS `t_role`;

CREATE TABLE `t_role` (

  `role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色ID',

  `role_name` varchar(18) DEFAULT NULL COMMENT '角色名',

  PRIMARY KEY (`role_id`)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `t_role` */

insert  into `t_role`(`role_id`,`role_name`) values (1,'admin'),(2,'root'),(3,'you'),(4,'屈原');

/*Table structure for table `t_user` */

DROP TABLE IF EXISTS `t_user`;

CREATE TABLE `t_user` (

  `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',

  `login_name` varchar(30) DEFAULT NULL COMMENT '用户名',

  `login_pass` varchar(65) DEFAULT NULL COMMENT '密码',

  PRIMARY KEY (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

insert into `t_user`(`user_id`,`login_name`,`login_pass`) values (1,'hjj','$2a$10$Mx24DvBBzoMC4gfHeuADx.wyK1G3PMYtWhFAH89Gjp6XjlbTeg0XC'),(2,'cw','$2a$10$Mx24DvBBzoMC4gfHeuADx.wyK1G3PMYtWhFAH89Gjp6XjlbTeg0XC'),(3,'yyqx','$2a$10$Mx24DvBBzoMC4gfHeuADx.wyK1G3PMYtWhFAH89Gjp6XjlbTeg0XC'),(4,'hhh','$2a$10$4o9XO2TB4QJzDJcP3J9vI.nApUZRD.sLXBDZzmbKQoNO6jqZdmAaS');

DROP TABLE IF EXISTS `t_user_role`;

CREATE TABLE `t_user_role` (

  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',

  `user_id` int(11) NOT NULL COMMENT '用户ID',

  `role_id` int(11) NOT NULL COMMENT '角色ID',

  PRIMARY KEY (`id`),

  KEY `user_id` (`user_id`),

  KEY `role_id` (`role_id`),

  CONSTRAINT `role_id` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`role_id`),

  CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

/*Data for the table `t_user_role` */

insert  into `t_user_role`(`id`,`user_id`,`role_id`) values (1,1,1),(2,1,2),(3,2,2),(4,3,3),(5,4,4),(6,3,2),(7,3,1),(8,4,2);

2. 新建项目

 2.1 导入相关的依赖

 <!--    父依赖 -->

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.3.4.RELEASE</version>

        <relativePath/>

    </parent>

    <properties>

        <java.version>1.9</java.version>

    </properties>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-security</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.thymeleaf.extras</groupId>

            <artifactId>thymeleaf-extras-springsecurity5</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.springframework.security</groupId>

            <artifactId>spring-security-test</artifactId>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

        </dependency>

        <dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>druid</artifactId>

            <version>1.1.21</version>

        </dependency>

        <dependency>

            <groupId>com.baomidou</groupId>

            <artifactId>mybatis-plus-boot-starter</artifactId>

            <version>3.4.2</version>

        </dependency>

        <!--mybatisplus代码生成-->

        <dependency>

            <groupId>com.baomidou</groupId>

            <artifactId>mybatis-plus-generator</artifactId>

            <version>3.4.1</version>

        </dependency>

        <!--模板-->

        <dependency>

            <groupId>org.apache.velocity</groupId>

            <artifactId>velocity-engine-core</artifactId>

            <version>2.2</version>

        </dependency>

        <dependency>

            <groupId>io.springfox</groupId>

            <artifactId>springfox-swagger2</artifactId>

            <version>2.9.2</version>

        </dependency>

        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->

        <dependency>

            <groupId>io.springfox</groupId>

            <artifactId>springfox-swagger-ui</artifactId>

            <version>2.9.2</version>

        </dependency>

        <dependency>

            <groupId>org.projectlombok</groupId>

            <artifactId>lombok</artifactId>

        </dependency>

    </dependencies>

2.2  配置application.yml

修改你自己的数据库名,用户名和密码

你的实体类的全类名

spring:
  servlet:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis-role?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource


mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true #驼峰命名规则
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

  type-aliases-package: com.example.springsecurity002.entity
  mapper-locations: classpath*:mapper/*.xml
 

2.3写启动类

启动类上加

@MapperScan("com.example.springsecurity002.mapper")

扫描你自己接口的包

2.4 用mybatis-plus 生成代码

    

        

/**

 * 生成代码

 *

 */

public class GeneratorApp {

    public static void main(STRING[] args) {

        // 1、创建代码生成器

        AutoGenerator mpg = NEW AutoGenerator();

        // 2、全局配置

        GlobalConfig gc = NEW GlobalConfig();

        //获得当前项目的路径(物理路径)

        STRING projectPath = System.getProperty("user.dir");

        //如果是子工程,则需要写成

        //STRING projectPath = System.getProperty("user.dir")+"子工程的名称";

        //设置生成的路径

        gc.setOutputDir(projectPath + "/src/main/java");

        //设置作者

        gc.setAuthor("hjj");

        //生成后是否打开所在文件夹

        gc.setOpen(FALSE);

        //生成Swagger2注解(需要导包)

        gc.setSwagger2(TRUE);

        //重新生成时文件是否覆盖

        gc.setFileOverride(TRUE);

        //设置实体类的名字

        gc.setEntityName("%s");

        //设置mapper接口名

        gc.setMapperName("%sMapper");

        //设置mapper.xml文件名

        gc.setXmlName("%sMapper");

        //设置在mapper.xml中生成一个基础的<ResultMap>映射所有的字段

        gc.setBaseResultMap(TRUE);

        //设置业务逻辑类接口名(首字母I去掉)

        gc.setServiceName("%sService");

        //设置业务逻辑实现类名

        gc.setServiceImplName("%sServiceImpl");

        //将全局配置设置到AutoGenerator

        mpg.setGlobalConfig(gc);

        //主键策略

        gc.setIdType(IdType.ID_WORKER_STR);

        //定义生成的实体类中日期类型

        gc.setDateType(DateType.ONLY_DATE);

        // 3、数据源配置

        DataSourceConfig dsc = NEW DataSourceConfig();

        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis-role?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false");

        dsc.setDriverName("com.mysql.cj.jdbc.Driver");

        dsc.setUsername("root");

        dsc.setPassword("root");

        mpg.setDataSource(dsc);

        // 4、包配置:控制项目生成的包

        PackageConfig pc = NEW PackageConfig();

        //完整包名

        pc.setParent("com.example.springsecurity002");

        //设置模块名,可以省略不写或null,如果写了就是com.example.模块名

        pc.setModuleName(NULL);

        //创建controller包名

        pc.setController("controller");

        //创建实体类包名

        pc.setEntity("entity");

        //创建业务逻辑层包名

        pc.setService("service");

        //创建mapper包名

        pc.setMapper("mapper");

        mpg.setPackageInfo(pc);

        //=====================================================

        // 自定义配置

        InjectionConfig cfg = NEW InjectionConfig() {

            @Override

            public void initMap() {

                // TO DO nothing 注:这里不需要写任何内容

            }

        };

// 如果模板引擎是 freemarker

// STRING templatePath = "/templates/mapper.xml.ftl";

// 如果模板引擎是 velocity

        STRING templatePath = "/templates/mapper.xml.vm";

// 自定义输出配置

        LIST<FileOutConfig> focList = NEW ArrayList<>();

// 自定义配置会被优先输出

        focList.add(NEW FileOutConfig(templatePath) {

            @Override

            public STRING outputFile(TableInfo tableInfo) {

                //自定义输出文件名,如果Entity设置了前后缀、此处注意xml的名称会跟着发生变

                RETURN projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;

            }

        });

        cfg.setFileOutConfigList(focList);

        mpg.setCfg(cfg);

        //====================================================================================

        // 5、策略配置

        StrategyConfig strategy = NEW StrategyConfig();

        //去掉表前缀

//        strategy.setTablePrefix("cms_");

        strategy.setTablePrefix("t_");

        //表名映射到实体的命名策略(下划线转驼峰)

        strategy.setNaming(NamingStrategy.underline_to_camel);

        //字段名映射到实体的命名策略(下划线转驼峰)

        strategy.setColumnNaming(NamingStrategy.underline_to_camel);

        //实体类是否支持lombok 模型 @Accessors(CHAIN = TRUE) setter链式操作

        strategy.setEntityLombokModel(TRUE);

        //controller类上是否使用@RestController

        strategy.setRestControllerStyle(TRUE);

        //对那一张表生成代码(多个用逗号分开)

        //strategy.setInclude("cms_user", "cms_role");

        //也可以按表的前缀来生成(如将所有以cms_开头的表)

//        strategy.setLikeTable(NEW LikeTable("cms_"));

        strategy.setLikeTable(NEW LikeTable("t_"));

        //生成实体时去掉表前缀

        strategy.setTablePrefix(pc.getModuleName() + "_");

        mpg.setStrategy(strategy);

        // 6、执行代码生成

        mpg.execute();

    }

}

3. 写业务逻辑

3.1. UserMapper

             

@Component

@Mapper

public interface UserMapper extends BaseMapper<User> {

    User findUserByName(String username);

}

3.2. UserService 和 UserServiceImpl 

public interface UserService extends IService<User> {

    User findUserByName(String username);

}


@Service

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired

    private UserMapper userMapper;

    @Override

    public User findUserByName(String username) {

        return userMapper.findUserByName(username);

    }

}

3.3UserMapper.xml 

<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.example.springsecurity002.entity.User">
    <id column="user_id" property="userId" />
    <result column="login_name" property="loginName" />
    <result column="login_pass" property="loginPass" />

    <collection property="roleList" ofType="com.example.springsecurity002.entity.Role">
        <id column="role_id" property="roleId" />
        <result column="role_name" property="roleName" />

    </collection>

</resultMap>


<select id="findUserByName" resultMap="BaseResultMap">

    select t1.*,t3.* from t_user t1
    left join t_user_role t2
    on t1.user_id = t2.user_id
    left join t_role t3
    on t2.role_id = t3.role_id
    where login_name = #{username}

</select>

3.4 在实体类加上 属性

@ApiModelProperty(value = "用户拥有的权限列表")
List<Role> roleList ;

3.5 自定义UserDetailsService

spring security在认证过程中需要查找用户,会调用UserDetailsService的loadUserByUsername方法得到一个UserDetails

@Component

public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口

    @Autowired

    UserService userService;

    @Override

    public UserDetails loadUserByUsername(String username) { //重写loadUserByUsername 方法获得 userdetails 类型用户

        User user = userService.findUserByName(username);

        if(user == null){

            throw new UsernameNotFoundException("用户名不存在");

        }

        List<SimpleGrantedAuthority> authorities = new ArrayList<>();

        //用于添加用户的权限。只要把用户权限添加到authorities 就万事大吉。

        for(Role role:user.getRoleList()) {

            authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName()));

            System.out.println(role.getRoleName());

        }

        return new org.springframework.security.core.userdetails.User(user.getLoginName(),

                user.getLoginPass(), authorities);

    }

}

org.springframework.security.core.authority.AuthorityUtils.createAuthorityList(String...)

工具方法获取创建 SimpleGrantedAuthority 对象添加角色时需要手动在角色名称前

加“ROLE_”前缀。

​​​​​​​3.6  写SpringSecurity 的配置类

@Configuration

@EnableWebSecurity

public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired

    private CustomUserService customUserService;

    //链式编程

    // 授权

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()//对所有请求进行授权

                .antMatchers("/user/**").hasRole("admin")

                .antMatchers("/product/**").hasRole("root")

                .anyRequest() //其他未设置的全部请求

                .authenticated() //需要认证

                .and()

                .formLogin() //设置未授权请求跳转到登录页面:开启表单登录功能

                .loginPage("/login") //自定义 登录页

                .permitAll()

                .and()

                .logout().permitAll();

    }

    //    认证

    @Override

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(customUserService).passwordEncoder(new BCryptPasswordEncoder()); ; //user Details Service验证

    }

}

​​​​​​​3.6 写页面

登录页面

login.html

<form name="form" th:action="@{/login}" action="/login" method="POST">
    <div>
        <label>账号</label>
        <input type="text" name="username" value="" placeholder="请输入用户名" />
    </div>
    <div>
        <label>密码</label>
        <input type="password"  name="password" placeholder="请输入密码" />
    </div>
    <input type="submit" id="login" value="Login"/>
</form>

首页

home.html

<div>
    <!--如果未登录-->
    <div sec:authorize="!isAuthenticated()">
        <a class="item" th:href="@{/login}">
            <i class="address card icon"></i> 登录
        </a>
    </div>
    <!--如果已登录-->
    <div sec:authorize="isAuthenticated()">
        <a class="item">
            <i class="address card icon"></i>
            用户名:<span sec:authentication="principal.username"></span>
            角色:<span sec:authentication="principal.authorities"></span>
        </a>
    </div>
  <form th:action="@{/logout}" method="post">
    <input type="submit" class="btn btn-primary" value="注销"/>
</form>

</div>

3.7 配置要跳转的路径

@Configuration

public class MyMvcConfig implements WebMvcConfigurer {

    // 配置视图跳转

    @Override

    public void addViewControllers(ViewControllerRegistry registry) {

       registry.addViewController("/").setViewName("home");

       registry.addViewController("/login").setViewName("login");

    }

}

4. 测试

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值