1-1 shiro与springboot入门(springboot+mybatis+shiro+thymleaf)

shiro与springboot入门(springboot+mybatis+shiro+thymleaf)

项目结构

01-demo
    |--com.demo
        |--ShiroApplication(启动类)
        |--bean(java实体对象)
            |--Permission,Role,User
        |--config(配置文件)
            |--ShiroConfig
        |--controller(控制器)
            |--LoginController,UserController
        |--mapper(mapper接口)
            |--PermissionMapper,RoleMapper,UserMapper
        |--realm
            |--ShiroRealm
        |--service(Service类)
            |--UserService
    |--resource
        |--config(配置文件)
            |--application.properties,logback-spring.xml
        |--mapper.shiro(mapper文件)
            |--PermissionMapper,RoleMapper,UserMapper
        |--templages(页面文件)
            |--index.xml,login.xml,unauthorized.xml
        |--data.sql(数据库脚本)

一、项目搭建

1.1、创建基础项目,添加引用库


        org.springframework.boot
        spring-boot-starter-parent
        1.5.6.RELEASE
    
        UTF-8
        UTF-8
        1.8
        3.0.2.RELEASE
        2.1.1
    
说明:
  • thymeleaf对应的版本是thymeleaf目前需要添加的版本

1.2、当前项目添加引用


        
            org.springframework.boot
            spring-boot-starter-thymeleaf
            1.5.4.RELEASE
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.1
        
        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            1.2.3
        
        
        
            mysql
            mysql-connector-java
        
        
            org.springframework
            spring-web
        
        
        
            org.apache.shiro
            shiro-spring
            1.4.0
        
        
        
            com.github.theborakompanioni
            thymeleaf-extras-shiro
            2.0.0
        
        
            org.thymeleaf
            thymeleaf
            3.0.5.RELEASE
        

1.3、配置文件:application.properties

#配置tomcat
server.port=2001
server.servlet-path=/
​
#关闭默认模板引擎缓存
spring.thymeleaf.cache=false
​
#配置日志文件
logging.config=classpath:config/logback-spring.xml
​
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/shiro_demo?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = 123123
​
#mybatis配置
mybatis.mapperLocations=classpath*:mapper/**/*.xml

二、数据准备

2.1、数据表创建:data.sql

2.2、实体对象创建

public class Permission {
    private Integer id;
    private Integer parent_id;
    private String parent_ids;
    private String permission;
    private String resource_type;
    private String url;
    private String name;
    private String available;
    private Set roles = new HashSet<>();
public class Role {
    private Integer id;
    private String role;
    private String description;
    private String available;
    private Set users = new HashSet<>();
    private Set permissions = new HashSet<>();
public class User {
    private Integer uid;
    private String username;
    private String password;
    private String name;
    private String id_card_num;
    private String state;
    private Set roles = new HashSet<>();
对象关系说明:
  • 1、一个User对应多个Role
  • 2、一个Permission对应多个Role
  • 3、一个Role对应多个User和多个Permission

2.3、mapper接口创建:

  • UserMapper:通过用户名获取用户操作,用户添加操作,用户删除操作
  • RoleMapper:通过用户id获取用户所有角色操作
  • PermissionMapper:通过用户所有角色获取用户所有权限操作
@Mapper
public interface UserMapper {
    User findByUserName(String userName);
​
    int insert(User user);
​
    int del(@Param("username") String username);
}
@Mapper
public interface RoleMapper {
​
    Set findRolesByUserId(@Param("uid") Integer uid);
​
}
@Mapper
public interface PermissionMapper {
    Set findPermissionsByRoleId(@Param("roles") Set roles);
}
获取用户资料操作
  • 1、通过shiro登录成功
  • 2、通过用户名称调用UserMapper获取用户信息
  • 3、通过用户信息调用RoleMapper获取用户角色列表
  • 4、通过用户角色列表调用PermissionMapper获取用户权限列表

2.4、mapper文件

  • mapper接口的具体实现
  • PermissionMapper.xml



    
  • RoleMapper.xml



    
  • UserMapper.xml



    
    
    
    
        
            SELECT
            LAST_INSERT_ID()
        
        insert into user_info
        
            
                uid,
            
            
                username,
            
            
                password,
            
            
                `name`,
            
            
                id_card_num,
            
            
                state,
            
        
        
            
                #{uid},
            
            
                #{username},
            
            
                #{password},
            
            
                #{name},
            
            
                #{id_card_num},
            
            
                #{state},
            
        
    
    
        DELETE FROM user_info WHERE username = #{username}
    

2.5、service层:UserService

  • 通过调用mapper接口进行具体操作
@Service
public class UserService {
​
    @Autowired
    private UserMapper userMapper;
​
    public int insert(User user) {
        return userMapper.insert(user);
    }
​
    public int del(String username) {
        return userMapper.del(username);
    }
}

三、权限相关配置:ShiroRealm,ShiroConfig

  • ShiroRealm:shiro中通过Realm来获取用户的信息
  • ShiroConfig:定义访问规则
package com.shiro.realm;
​
import com.shiro.bean.Permission;
import com.shiro.bean.Role;
import com.shiro.bean.User;
import com.shiro.mapper.PermissionMapper;
import com.shiro.mapper.RoleMapper;
import com.shiro.mapper.UserMapper;
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.springframework.beans.factory.annotation.Autowired;
​
import java.util.Set;
​
/**
 * @author brusion
 * @date 2018/10/18
 * @description: Realm用于获取用户数据,组装后给shiro使用
 */
public class ShiroRealm extends AuthorizingRealm {
​
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
​
​
    //验证当前登录的账号是否可用
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
​
        UsernamePasswordToken tokenUser = (UsernamePasswordToken) token;
        String username = tokenUser.getUsername();
        String password = new String(tokenUser.getPassword());
​
        User user = userMapper.getByName(username);
        if (user == null || !password.equals(user.getPassword())) {
            throw new UnknownAccountException("用户或密码为空");
        }
​
        if ("1".equals(user.getState())) {
            throw new LockedAccountException("账号被锁定");
        }
​
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
​
    //获取当账号对应的权限,角色信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
​
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
​
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Integer uid = user.getUid();
​
        Set roles = roleMapper.getRoleById(uid);
        for (Role role : roles) {
            info.addRole(role.getRole());
        }
​
        Set permissions = permissionMapper.getPermissionByRole(roles);
        for (Permission per : permissions) {
            info.addStringPermission(per.getPermission());
        }
​
        return info;
    }
}

说明:
  • doGetAuthenticationInfo:用于验证用户账号密码是否正确,用户是否为可用账号
  • doGetAuthorizationInfo:通过mapper层获取用户数据,并封装到Realm中的通用对象中供realm中使用
package com.shiro.config;
​
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.shiro.realm.ShiroRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
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.LinkedHashMap;
​
/**
 * @author brusion
 * @date 2018/10/18
 * @description:
 */
@Configuration
public class ShiroConfig {
​
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
​
        //配置权限访问规则
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
​
        factoryBean.setSecurityManager(securityManager);
        factoryBean.setLoginUrl("/login");
        factoryBean.setSuccessUrl("/index");
        factoryBean.setUnauthorizedUrl("/unauthorized");
​
        LinkedHashMap map = new LinkedHashMap<>();
        map.put("/login", "anon");
        map.put("/", "anon");
        map.put("/css/**", "anon");
        map.put("/img/**", "anon");
        map.put("/ijs/**", "anon");
        map.put("logout", "logout"); //退出登录
        map.put("/**", "authc"); //其他资源都需要登录
​
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }
​
    //事务管理器
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(shiroRealm);
        return manager;
    }
​
    //生命周期处理器
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
​
    @Bean
    public ShiroRealm shiroRealm() {
        return new ShiroRealm();
    }
​
​
    //模板使用shiro标签
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
​
}

说明:
  • shiroFilter:配置主要的拦截规则如:页面设置,资源访问设置

四、请求操作

  • LoginController:登录相关操作及对应页面跳转
  • UserController:用于用户对应的接口操作
@Controller
public class LoginController {
​
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String userLogin(String username, String password, HttpSession session,Model model) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            User user = (User) subject.getPrincipal();
            model.addAttribute("user",user);
            session.setAttribute("user", user);
            return "index";
        } catch (Exception e) {
            return "login";
        }
    }
​
​
    @RequestMapping("/")
    public String root() {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        if (user == null) {
            return "redirect:/login";
        } else {
            return "redirect:/index";
        }
    }
​
    @RequestMapping("/login")
    public String login() {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        if (user == null) {
            return "login";
        } else {
            return "redirect:/index";
        }
    }
​
    @RequestMapping("/index")
    public String index(Model model) {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        if (user == null) {
            return "login";
        } else {
            model.addAttribute("user",user);
            return "index";
        }
    }
​
    @RequestMapping("/logout")
    public String logout(Model model) {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        model.addAttribute("msg", "安全退出");
        return "login";
    }
​
​
    /**
     * 无权限页面
     */
    @RequestMapping("/unauthorized")
    public String unauthorized() {
        return "unauthorized";
    }
​
}
​
@RestController
@RequestMapping("/user")
public class UserController {
​
    @Autowired
    private UserService userService;
​
    @RequiresPermissions("user:add")
    @RequestMapping("/add")
    public String add() {
        User user = new User();
        user.setName("test-name" + System.currentTimeMillis());
        user.setUsername("test-name");
        userService.insert(user);
​
        return "用户添加成功";
    }
​
    @RequiresPermissions("user:del")
    @RequestMapping("/del")
    public String delete() {
        userService.delete("test-name");
​
        return "用户删除成功";
    }
​
​
    @RequiresPermissions("user:add")
    @RequestMapping("/view")
    public String list() {
        return "列表数据";
    }
}
​

五、前端页面

  • index.xml



    
    Insert title here



点我注销
  • login.xml



    
    Insert title here


欢迎登录

用户名:
密码:
  • unauthorized.xml



    
    Insert title here


对不起,您没有权限

六、启动测试

@SpringBootApplication
public class ShiroApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class, args);
    }
}

6.2、测试

  • admin角色测试
地址:http://localhost:2001/
账号密码:admin  123456
登录成功操作:添加用户操作,查看用户操作(调用UserController接口数据)
退出登录操作:
  • test角色测试
地址:http://localhost:2001/
账号密码:test  123456
登录成功操作:删除用户操作(调用UserController接口数据)
退出登录操作:

源码地址:

你可能感兴趣的:(微服务-spring,boot,shiro,鉴权中心)