springboot-mybatis-shiro 整合

springboot整合shiro---小白进阶之路

shiro: 授权于认证

----认证,通过一个token来对比用户名与密码是否一致

----授权,比对成功后,授予权限,这里授予的权限是需要与数据库逻辑一致的,shiro中有一个 perms 关键词,拥有某个资源的权限才可以访问 

如:perms[admin] 那么登录我的admin用户就可以给他授权,访问哪~ 

--shiro框架,简单也简单,难也难,反正我个人觉得我应该算入门吧~作为一个新手小白,给想学的新手小白整一个shiro,有什么地方做错了 记得点出来哈

依赖:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</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.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>
<!--thymeleaf依赖-->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<!--shiro-thymeleaf整合-->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

<!--数据库日志数据源mybatis适配包lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>

<!--shiro依赖-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.7.1</version>
</dependency>

第一步:

需要三张数据库,用户表,角色表,用户角色中间表来进行授权于认证

做几个测试数据

User 表(角色表):

perm表(角色):

user_Id_perm

第二步:

1.打开idea新建一个spring项目,项目名字随意

1.1打开application.yml 配置我们 数据库的连接,以及mybatis扫描等...

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/shirotest?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: cn.tedu.shiros.entity

server:
  port: 80

1.2创建实体类

User与Perm,一般是在pojo或者是entity,看个人习惯吧

package cn.tedu.shirotwo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Data //生成get和set
@AllArgsConstructor//构造方法
@NoArgsConstructor//无参构造
@Component//给spring进行管理 个人爱好 这段可以省略
public class Perm {

    //权限ID
    private Integer pid;

    //用户名
    private String permname;

    //权限名
    private String  detail;



}
package cn.tedu.shirotwo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;


@Data //生成get和set
@AllArgsConstructor//构造方法
@NoArgsConstructor//无参构造
@Component//给spring进行管理 个人爱好 这段可以省略
public class User {

    //用户id
    private Integer uid;

    //用户名
    private String username;

    //密码
    private String password;

    //权限信息---这一步是为了我们后面通过用户登录获取权限
    private Perm perm;
}

1.3 创建我们的mapper层,mapper是访问数据库的~一般是放在dao层或者是mapper层,这里我就直接创建dao层与mybatis/mapper/*.xml文件了

这里我要给各位科普一下为什么要创建xml文件,我们用mybatis的原因是因为 轻量级,松耦合,持久性等

用传统的jdbc 代码量大且重复,而且不易维护,mybatis呢 xml形式,易操作可扩展功能,当然现在也有一个mybatis-plus,xml都不用写了,言归正传

里面就一个方法,通过我们的用户名去查询数据库是否存在username

package cn.tedu.shirotwo.dao;

import cn.tedu.shirotwo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {
    //根据用户名查询用户(登录时校验用户用)
    User queryByUsername(String username);
}

 

<?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="cn.tedu.shirotwo.dao.UserMapper">
    <select id="queryByUsername" parameterType="String" resultMap="UserMap" >
      SELECT *
        FROM
        user u,
        perm p,
        user_Id_perm up
        WHERE u.username=#{username}
        AND u.uid=up.uid
        AND p.pid=up.pid
    </select>
<resultMap id="UserMap" type="User">
    <id property="uid" column="uid"/>
    <result property="username" column="username"/>
    <result property="password" column="password"/>
 <association property="perm" javaType="Perm">
     <id property="pid" column="pid"/>
     <result property="permname" column="permname"/>
     <result property="detail" column="detail"/>
 </association>
</resultMap>
</mapper>

测试下--

OK 有数据--

1.4 编辑我们的service层,这里指的是数据层,如果有需要增强的与    数据库交互       业务在这里编写,我们所谓的entity-dao-service-controller-web-config等 都是为了分而治之,区分每块自己做的工作

package cn.tedu.shirotwo.service;

import cn.tedu.shirotwo.entity.User;

public interface UserService {
    //根据用户名查询用户(登录时校验用户用)
    User queryByUsername(String username);
}

 package cn.tedu.shirotwo.service.impl;

import cn.tedu.shirotwo.dao.UserMapper;
import cn.tedu.shirotwo.entity.User;
import cn.tedu.shirotwo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public User queryByUsername(String username) {
        return userMapper.queryByUsername(username);
    }
}

1.5 开始重点shiro框架编写

package cn.tedu.shirotwo.config;

import cn.tedu.shirotwo.entity.User;
import cn.tedu.shirotwo.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("进入授权");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Subject subject= SecurityUtils.getSubject();//通过这个对象获取能登陆用户
        User currentUser = (User) subject.getPrincipal();//获取当前登录对象
        info.addStringPermission(currentUser.getPerm().getPermname());//获取权限
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("进入认证");
        //获取前端发来的token对象 里面存了用户名和密码
        UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
        //将token里的用户名查询数据库是否存在
        User user=userService.queryByUsername(token.getUsername());
        if(user==null){
            return null;//这里是直接返回账户名错误UnknownAccountException 这个对象
        }

            //这一步是认证密码是否正确
           return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}
package cn.tedu.shirotwo.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
/*1.Realm,realm可以理解为一个域,
里面存放了用户的数据,
我们securityManage要验证用户身份,需要从这里获取这是第一步
*/

    @Bean
    public UserRealm realm(){
        return new UserRealm();
    }

  //2.DefaultWebSecurityManager
@Bean("sec")
public DefaultWebSecurityManager securityManager(@Qualifier("realm")UserRealm realm){
        //关联userRealm
        DefaultWebSecurityManager SecurityManager=new DefaultWebSecurityManager();
    SecurityManager.setRealm(realm);
        return SecurityManager;
    }

    //ShiroFilterFactoryBean 过滤器,权限认证在这里操作
@Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("sec") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);//设置安全管理器
    Map<String ,String> map=new HashMap();
   /*
        anon:无须认证就可以访问
        authc:必须认证了才可以访问
        user:必须拥有 记住我 才能访问
        perms:拥有对某个资源的权限才能访问
        role:拥有某项权限才可以访问
        */
    map.put("/admin/*", "perms[admin]");
    map.put("/test/*", "perms[test]");
    map.put("/test/*", "perms[admin]");
    map.put("/guest/*", "perms[guest]");
    bean.setFilterChainDefinitionMap(map);
    //如果权限不够就会发起的请求(路由请求,返回没有权限)
    bean.setUnauthorizedUrl("/unauthor");
    //如果没有认证就会发送的请求请求(路由请求,让用户登录)
    bean.setLoginUrl("/toLogin");
    return bean;
}

}

第三步:

编写web,分为三个内容

1:login 登录 index 首页 权限对应的展示页面

index:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">>
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<span th:text="${msg}" style="color: red;"></span>
<a th:href="@{/admin/admin}">admin</a>||<a th:href="@{/test/test}">test</a>||<a th:href="@{/guest/guest}">guest</a>
</body>
</html>

login:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<span th:text="${msg}" style="color: red;"></span>
<form th:action="@{/login}" name="login" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>

</body>
</html>

admin:

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

test:

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

guest:

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

这里编写完成了,开始最后的controller:

controller我分为三步

第一:首页与权限不足,以及跳转登录

第二:我的表单提交到login验证

第三:进入admin。test。guest 界面

第一:

package cn.tedu.shirotwo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {



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


    @RequestMapping("/toLogin")
public String toLogin(){
        return "login";
    }
    @RequestMapping("/unauthor")
    @ResponseBody
    public String toUnauthor(){
        return "您的权限不足";
    }
}

第二:

import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class LoginController {

    @RequestMapping("/login")
    public String login(@RequestParam("username")String username,
                        @RequestParam("password")String password,
                        Model model
                        ){
        //获取当前用户
        Subject subject=SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(username,password);

            try {
                subject.login(token);
                return "index";
            }catch (UnknownAccountException e){
            model.addAttribute("msg", "用户名错误");
            return "login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg", "密码错误");
                return "login";
            }

    }
}

 

第三:

package cn.tedu.shirotwo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class AllurlController {

    @RequestMapping("/admin/admin")
    public String admin(){
        return "/admin/admin";
    }
    @RequestMapping("/test/test")
    public String test(){
        return "/test/test";
    }
    @RequestMapping("/guest/guest")
    public String guest(){
        return "/guser/guest";
    }
}

测试:

http://localhost/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值