SpringBoot 04 shiro数据认证及登录

发布时间 2023-10-18 17:34:32作者: OYそ
 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class RUser {
    @TableId(value="usr_id",type = IdType.AUTO)
    private Integer usrId;
    private String usrName;
    private  String usrAccount;
    private  String  usrPassword;
    private  String  usrSalt;
    private  String  usrClazz;
    @TableField(exist = false)
    private Set<Role> roleSet;
}

mapper

@Mapper
public interface RUserMapper extends BaseMapper<RUser> {
}

service

@Transactional
public interface UserService {
    RUser queryByAccount(String account);
}

service实现类

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private RUserMapper userMapper;
    @Override
    public RUser queryByAccount(String account) {
        QueryWrapper<RUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("usr_account",account);
        RUser user = userMapper.selectOne(userQueryWrapper);
        return user;
    }
}

首页

<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<meta charset="UTF-8">
<body>
    <h1>INDEX!!!</h1>
    <img src="../img/waji.jpg">
    <shiro:notAuthenticated>
        <a href="/login">登录</a>
    </shiro:notAuthenticated>
    <shiro:authenticated><!--从会话中那,会话中是user对象-->
        welcome:<strong><shiro:principal property="usrName"/></strong> logining!!
        <a href="/logout">退出</a>
    </shiro:authenticated>

</body>
</html>

登录

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>登录</title>

</head>
<body>

    <article>
        <h1>登录</h1>
        <form action="login" method="post" >
            账号:<input type="text" name="account" ><br>
            密码:<input type="text" name="password"><br>
            <input type="submit" value="提交"><br>
            <span id="tip" style="color: red;" th:text="${tip}">默认值</span><br>
        </form>
    </article>

</body>
</html>

配置

application.yml

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/shiro?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123
logging:
  level:
    com.mapper: trace
    org.springframework.jdbc: trace
# server:
#  port: 9999
 # servlet:
 #   context-path: /ssm
mybatis-plus:
  type-aliases-package: com.entity

启动器

package com;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.realm.MyRealm;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.LinkedHashMap;
import java.util.Map;


@SpringBootApplication
@MapperScan("com.mapper")
public class SpringBoot02Application {

    public static void main(String[] args) {
        ApplicationContext ac = SpringApplication.run(SpringBoot02Application.class, args);
        System.out.println("访问:http://localhost:8080");
    }
    /*添加分页插件*/
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
/* shiro相关配置*/
    @Bean //密码匹配器
    public SimpleCredentialsMatcher simpleCredentialsMatcher(){//简单的匹配规则,没有加密配置
        SimpleCredentialsMatcher simpleCredentialsMatcher =new SimpleCredentialsMatcher();
        return simpleCredentialsMatcher;
    }
    //会话管理器
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        return defaultWebSessionManager;
    }
    @Bean // 安全管理器
    public DefaultWebSecurityManager defaultWebSecurityManager(SimpleCredentialsMatcher simpleCredentialsMatcher,
                                                               MyRealm realm, DefaultWebSessionManager defaultWebSessionManager) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        realm.setCredentialsMatcher(simpleCredentialsMatcher);
        defaultWebSecurityManager.setRealm(realm);
        defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);
        return defaultWebSecurityManager;
    }

    //过滤法则
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); //有顺序  不用无序的HashMap
        //放行
        //静态资源放行
        filterChainDefinitionMap.put("/favicon.ico","anon");
        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/img/**","anon");

        //动态资源放行
        filterChainDefinitionMap.put("/","anon");
        filterChainDefinitionMap.put("/a","anon");
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/logout","logout");

        //不放行
        filterChainDefinitionMap.put("/**","authc");
        //未认证跳往地址
        shiroFilterFactoryBean.setLoginUrl("/");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;

    }
    //方言
    @Bean
    public ShiroDialect shiroDialect(){
        ShiroDialect shiroDialect=new ShiroDialect();
        return shiroDialect;
    }

}

pom.xml

    <dependencies>
        <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>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>  <!--mysql5以及之前使用的是:com.mysql.jdbc. Driver
            mysql6以及之后使用的是: com.mysql.cj.jdbc.Driver 若配置文件爆红则把版本去掉,或先把标签换成compile,再换回来runtime             -->
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.8.0</version>
        </dependency>
        <!--方言-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.1.0</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>
    </dependencies>


  

UserController

package com.controller;


import com.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class UserController {

     @GetMapping("/login")
     public String login(){
         return "login";
     }
     @PostMapping("/login")
     public String login(String account, String password, Model model){
         Subject subject = SecurityUtils.getSubject();
         try {
             subject.login(new UsernamePasswordToken(account,password));
             return "redirect:/";
         }catch (UnknownAccountException e){
             model.addAttribute("tip","账号不存在");
             return "login";
         }catch (AuthenticationException e){
             model.addAttribute("tip","账号或密码错误");
             return "login";
         }


     }

}

首页:

 失败:

 成功: