其他分享
首页 > 其他分享> > springboot整合shrio

springboot整合shrio

作者:互联网

1.创建项目导入相关依赖


数据库:自己创建。

1.1、创建一个springboot-shrio,并在pom.xml导入如下依赖。

<dependencies>

    <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>

        <!--mybatis和springboot整合包-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--数据源-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>

        <!--jdbc驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--log4j-->
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--spring-shiro整合包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.3</version>
        </dependency>

        <!--shiro-thymeleaf整合-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

2.整合mybatis


2.1创建数据源application-db.yml配置文件,并添加如下配置。

spring:
  datasource:
    username: root
    password: 123456
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

2.2创建需要的包,如以下结构
在这里插入图片描述
2.3在pojo包下创建User实体类,并添加以下全局变量。

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private Integer id;
    private String username;
    private String password;
    private String perms;
}

2.4在dao包下创建一个UserMapper接口,并添加以下抽象方法。

@Mapper
@Repository
public interface UserMapper {
    //登录,根据用户名查询用户信息
    public User queryUserByName(String name);
    //注册
    public User insertUserName(User user);
}

2.5在resources资源目录下创建mapper文件,然后在mapper包下创建UserMapper.xml配置文件,并在其中添加sql。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.itlhc.dao.UserMapper">

    <!--结果集映射-->
    <resultMap id="userMap" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="perms" column="perms"/>
    </resultMap>
    <!--登录,根据用户名查询用户信息-->
    <select id="queryUserByName" resultType="user" parameterType="String">
        select * from r_user where username = #{username};
  	</select>

    <!--注册-->
    <select id="insertUserName" parameterType="User" resultMap="userMap">
        insert into r_user(id,username,password,perms)values (#{id},#{username},#{password},#{perms});
    </select>

</mapper>

2.5在application.properties配置文件中,添加夹如下配置。

#配置端口
server.port=8081

#添加application-db.yml
spring.profiles.active=db

#为实体类设置别名
mybatis.type-aliases-package=com.itlhc.pojo

#绑定mapper.xml
mybatis.mapper-locations=classpath:mapper/*.xml

3.整合shiro


3.1在config配置类中创建一个ShrioConfig配置类,并添加如下Shrio服务代码。

@Configuration
public class ShrioConfig {

    //ShiroFilterFactoryBean : Step3
    @Bean
    public ShiroFilterFactoryBean getShrioFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /*
            anno: 无需认证就可以访问
            authc: 必须认证了才可以访问
            user: 必须拥有 记住我 功能才能用
            perms: 拥有对某个资源的权限才能访问
            role: 拥有某个角色权限才能访问
        */

        Map<String, String> filterMap = new LinkedHashMap<>();

        //用户授权,正常情况下没有授权会跳转到授权页面
        filterMap.put("/admin/*","role[admin3]");
        filterMap.put("/user/update","perms[user:update]");

        //拦截
        //filterMap.put("/user/add","authc");
        //filterMap.put("/user/update","authc");
        filterMap.put("/admin/*","authc");
        filterMap.put("/user/*","authc");


        //设置登录请求
        bean.setLoginUrl("/toLogin");
        //设置未授权页面
        bean.setUnauthorizedUrl("/noauth");

        bean.setFilterChainDefinitionMap(filterMap);
        return bean;

    }

    //DefaultWebSecurityManager : Step2
    @Bean("securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建 realm 对象, 需要自定义类:Step1
    @Bean
    public UserRealm userRealm(){
        //自定义授权
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(myCredentialsMatcher());
        return userRealm;
    }

    /*//创建 realm 对象, 需要自定义类:Step1
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }*/

    //整合 ShiroDialect:用来整合shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

    //自定义密码认证
    @Bean
    public MyCredentialsMatcher myCredentialsMatcher(){
        return new MyCredentialsMatcher();
    }

}

3.2在config包下创建UserRealm用户授权认证类,并添加相关代码。


//自定义的 UserRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserServiceImpl userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了 => doGetAuthorizationInfo");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        // 拿到User对象
        User currentUser = (User) subject.getPrincipal();
        // 设置当前用户的权限
        System.out.println(currentUser.getUsername() + "的权限为 " + currentUser.getPerms());
        info.addStringPermission(currentUser.getPerms());
        //设置用户角色
        info.addRole(currentUser.getUsername());

        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了 => 认证AuthenticationToken");

        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        //连接真实的数据库
        User user = userService.queryUserByName(userToken.getUsername());
        if(user == null){
            //没有这个人
            return null; //抛出异常 UnknownAccountException
        }

        // 登录成功 将用户信息存入session
        Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user.getUsername());

        // 密码认证,shiro做,可以自己定义密码比对类完成密码认证
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }


}

3.3在config包下创建MyCredetialsMatcher自定义密码校验类,并添加如下校验规则代码,我这里用MD5密码校验方式。

//自定义密码比对类
public class MyCredentialsMatcher extends SimpleCredentialsMatcher {
    @Autowired
    UserServiceImpl userService;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken uToken = (UsernamePasswordToken)token;
        //这个密码是客户提交的密码,即下面main函数中用new UsernamePasswordToken("javass","bb")提交的“bb”
        String inPassword = new String(uToken.getPassword());
        //这个密码是上面realm中给出的数据库密码,也就是正确的密码:String passWord = "428729c9b80aa3198300caabb24f8a88"
        //连接真实的数据库
        User user = userService.queryUserByName(uToken.getUsername());

        String encryptInPassword = MD5Util.pwdMd5(inPassword);
        return encryptInPassword.equals(user.getPassword());
    }

}

3.4在uitls包下创建MD5Util密码加密解密工具类,并添加如下加密代码。

//MD5加密解密工具类
public class MD5Util {
    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
            "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
     * 转换字节数组为16进制字串
     *
     * @param b 字节数组
     * @return 16进制字串
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte aB : b) {
            resultSb.append(byteToHexString(aB));
        }
        return resultSb.toString();
    }

    /**
     * 转换byte到16进制
     *
     * @param b 要转换的byte
     * @return 16进制格式
     */
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }


    /**
     * 密码加密
     *
     * @param password
     * @return
     */
    public static String pwdMd5(String password) {
        String pwdMd5 = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(password.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            pwdMd5 = sb.toString().toLowerCase();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pwdMd5;
    }
}

3.5在controller包下创建MyController控制类,并添加如下控制代码。

@Controller
public class MyController {

    @Autowired
    private UserService service;

    @RequestMapping({"/","/index"})
    public String toIndex(Model model){
        model.addAttribute("msg","hello,Shrio");
        return "index";
    }

    @RequestMapping("/user/add")
    public String add(){
        return "user/add";
    }

    @RequestMapping("/user/update")
    public String update(){
        return "user/update";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/login")
    public String login(@RequestParam("username") String name, @RequestParam("password") String password, Model model){
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        try {
            subject.login(token); // 执行登录方法,如果没有异常就说明OK了
            return "index";
        }catch (UnknownAccountException accountException){
            // 用户名不存在
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            // 密码错误
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "未经授权无法访问此页面!";
    }

    @RequestMapping("/ZRegister")
    public String ZRegister(){
        return "register";
    }

    @RequestMapping("/register")
    public String register(User user){
        service.insertUserName(user);
        return "index";
    }
    @RequestMapping("logout")
    public String logout(){
        // 拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "index";
    }

    @RequestMapping("/adminUser")
    public String adminUser(){
        return "admin/adminUser";
    }
}

4.html页面


4.1index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<h1 th:text="${msg}"></h1>
<!--从session中判断值-->
<div shiro:guest="true">
<!--<div th:if="${session.loginUser == null}">-->
    <a th:href="@{/toLogin}">登录</a>
</div>

    <a th:href="@{/logout}">注销</a>
    <a th:href="@{/ZRegister}">注册</a>

<div shiro:hasPermission="user:add">
    <a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/user/update}">update</a>
</div>
<div shiro:hasRole="admin3">
    <a th:href="@{/adminUser}">admin</a>
</div>

</body>
</html>

4.2login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<p th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
    <p> 用户名:<input type="text" name="username"> </p>
    <p> 密码:<input type="password" name="password"> </p>
    <p> <input type="submit"> </p>
</form>

</body>
</html>

4.3register.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<form th:action="@{/register}">
    <p> 用户名:<input type="text" name="username"> </p>
    <p> 密码:<input type="password" name="password"> </p>
    <p> 权限:<input type="perms" name="perms"> </p>
    <p> <input type="submit"> </p>
</form>
</body>
</html>

4.4user文件中的add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>add</h1>
</body>
</html>

4.5user文件中的update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>update</h1>
</body>
</html>

4.6admin文件下的adminUser.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hello,admin</h1>
</body>
</html>

标签:return,String,密码,shrio,user,整合,new,public,springboot
来源: https://blog.csdn.net/zuohaozijiyuan/article/details/121273740