zoukankan      html  css  js  c++  java
  • spring boot集成shrio用于权限控制

    下面是一个简单的springBoot集成shrio的项目,技术是:spring boot+idea+gradle+shrio+mybatis

    1:首先在build.gradle中导入依赖

        

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE')
        }
    }
    group "com.li"
    version "1.0-SNAPSHOT"
    apply plugin: "java"                           //java 插件
    apply plugin: "org.springframework.boot"   //spring boot 插件
    apply plugin: "io.spring.dependency-management"
    
    apply plugin: "application"   //应用
    //mainClassName = "com.li.SpringBootShrioManaApplication"
    sourceCompatibility = 1.8
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-web",
                "org.springframework.boot:spring-boot-starter-activemq",
                "org.springframework.boot:spring-boot-starter-test",
                "org.springframework.boot:spring-boot-starter-cache",
                "org.springframework.boot:spring-boot-devtools",
                "mysql:mysql-connector-java:5.1.35",
                'org.apache.commons:commons-lang3:3.4',
                'org.apache.commons:commons-pool2',
                "org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.0",
                'org.apache.shiro:shiro-core:1.2.2',
                'org.apache.shiro:shiro-spring:1.2.2',
                'org.apache.shiro:shiro-ehcache:1.2.2',
                'org.apache.logging.log4j:log4j-core:2.7'
        )
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }

    2:创建sql表并导入数据。

    DROP TABLE IF EXISTS `module`;
    CREATE TABLE `module` (
      `mid` int(11) NOT NULL AUTO_INCREMENT,
      `mname` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`mid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of module
    -- ----------------------------
    INSERT INTO `module` VALUES ('1', 'add');
    INSERT INTO `module` VALUES ('2', 'delete');
    INSERT INTO `module` VALUES ('3', 'query');
    INSERT INTO `module` VALUES ('4', 'update');
    
    -- ----------------------------
    -- Table structure for module_role
    -- ----------------------------
    DROP TABLE IF EXISTS `module_role`;
    CREATE TABLE `module_role` (
      `rid` int(11) DEFAULT NULL,
      `mid` int(11) DEFAULT NULL,
      KEY `rid` (`rid`),
      KEY `mid` (`mid`),
      CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`),
      CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of module_role
    -- ----------------------------
    INSERT INTO `module_role` VALUES ('1', '1');
    INSERT INTO `module_role` VALUES ('1', '2');
    INSERT INTO `module_role` VALUES ('1', '3');
    INSERT INTO `module_role` VALUES ('1', '4');
    INSERT INTO `module_role` VALUES ('2', '1');
    INSERT INTO `module_role` VALUES ('2', '3');
    
    -- ----------------------------
    -- Table structure for role
    -- ----------------------------
    DROP TABLE IF EXISTS `role`;
    CREATE TABLE `role` (
      `rid` int(11) NOT NULL AUTO_INCREMENT,
      `rname` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`rid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of role
    -- ----------------------------
    INSERT INTO `role` VALUES ('1', 'admin');
    INSERT INTO `role` VALUES ('2', 'customer');
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `uid` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) DEFAULT NULL,
      `password` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES ('1', 'hlhdidi', '123');
    INSERT INTO `user` VALUES ('2', 'xyycici', '1992');
    
    -- ----------------------------
    -- Table structure for user_role
    -- ----------------------------
    DROP TABLE IF EXISTS `user_role`;
    CREATE TABLE `user_role` (
      `uid` int(11) DEFAULT NULL,
      `rid` int(11) DEFAULT NULL,
      KEY `u_fk` (`uid`),
      KEY `r_fk` (`rid`),
      CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`),
      CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user_role
    -- ----------------------------
    INSERT INTO `user_role` VALUES ('1', '1');
    INSERT INTO `user_role` VALUES ('2', '2');

    3:创建dao层pojo和mapper映射

    package com.li.dao.pojo;
    
    import java.util.Set;
    
    public class Module {
        private Integer mid;
        private String mname;
        private Set<Role> roles;
    
        public Integer getMid() {
            return mid;
        }
    
        public void setMid(Integer mid) {
            this.mid = mid;
        }
    
        public String getMname() {
            return mname;
        }
    
        public void setMname(String mname) {
            this.mname = mname;
        }
    
        public Set<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(Set<Role> roles) {
            this.roles = roles;
        }
    }
    package com.li.dao.pojo;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Role {
        private Integer rid;
        private String rname;
        private Set<User> users = new HashSet<>();
        private Set<Module> modules = new HashSet<>();
    
        public Integer getRid() {
            return rid;
        }
    
        public void setRid(Integer rid) {
            this.rid = rid;
        }
    
        public String getRname() {
            return rname;
        }
    
        public void setRname(String rname) {
            this.rname = rname;
        }
    
        public Set<User> getUsers() {
            return users;
        }
    
        public void setUsers(Set<User> users) {
            this.users = users;
        }
    
        public Set<Module> getModules() {
            return modules;
        }
    
        public void setModules(Set<Module> modules) {
            this.modules = modules;
        }
    }
    package com.li.dao.pojo;
    
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;
    
    public class User implements Serializable {
        private Integer uid;
        private String username;
        private String password;
        private Set<Role> roles = new HashSet<>();
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Set<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(Set<Role> roles) {
            this.roles = roles;
        }
    }

    UserMapper.java

    package com.li.dao.Mapper;
    
    import com.li.dao.pojo.User;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UserMapper {
        public User findByUserName(String username);
    }

    4:创建service层,UserService.java,UserServiceImpl.java

       

    package com.li.service;
    
    import com.li.dao.pojo.User;
    
    public interface UserService {
        User findUserByName(String username);
    }
    package com.li.service.impl;
    
    import com.li.dao.Mapper.UserMapper;
    import com.li.dao.pojo.User;
    import com.li.service.UserService;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserServiceImpl implements UserService{
        Logger logger = LogManager.getLogger(UserServiceImpl.class);
        @Autowired
        private UserMapper userMapper;
        @Override
        public User findUserByName(String username) {
            logger.warn(username);
            return userMapper.findByUserName(username);
        }
    }

    5:配置controller层

       

    package com.li.controller;
    
    import com.li.dao.pojo.User;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpSession;
    import java.lang.reflect.Method;
    
    @Controller
    public class LoginController {
    
        Logger logger= LogManager.getLogger(LoginController.class);
        @RequestMapping("/loginTest")
        public String login() {
            return "login.html";
        }
    
        @RequestMapping("/login")
        public String loginhtml() {
            return "/visitor/login.html";
        }
        @RequestMapping(value = "/loginUser")
        public String loginUser(String username,String password,HttpSession session) {
            UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
            Subject subject = SecurityUtils.getSubject();
            try {
    
                logger.info(username);
                logger.warn(usernamePasswordToken);
    
                //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
                //每个Realm都能在必要时对提交的AuthenticationTokens作出反应
                //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
    
                subject.login(usernamePasswordToken);   //完成登录
                logger.warn("success");
                User user=(User) subject.getPrincipal();
    
                session.setAttribute("user", user);
                return "/user/index.html";
            } catch(Exception e) {
                return "/visitor/login.html";//返回登录页面
            }
    
        }
        @RequestMapping("/logOut")
        public String logOut(HttpSession session) {
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
    //        session.removeAttribute("user");
            return "login";
        }
    }

    6:配置shrio和AuthRealm, matcher等。

       

    package com.li.web;
    import com.li.dao.pojo.Module;
    import com.li.dao.pojo.Role;
    import com.li.dao.pojo.User;
    import com.li.service.UserService;
    import com.li.service.impl.UserServiceImpl;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    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 sun.rmi.runtime.Log;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    
    public class AuthRealm extends AuthorizingRealm {
    
        Logger logger = LogManager.getLogger(AuthRealm.class);
        @Autowired
        private UserServiceImpl userService;
    
        //认证.登录
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
            String username = utoken.getUsername();
    
            logger.warn(username);
            User user = userService.findUserByName(username);  //使用mybatis从数据库中得到用户
            logger.warn(user.getUsername());
    
            return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码
        }
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户
            List<String> permissions=new ArrayList<>();
            Set<Role> roles = user.getRoles();
            if(roles.size()>0) {
                for(Role role : roles) {
                    Set<Module> modules = role.getModules();
                    if(modules.size()>0) {
                        for(Module module : modules) {
                            permissions.add(module.getMname());
                        }
                    }
                }
            }
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
            info.addStringPermissions(permissions);//将权限放入shiro中.
            return info;
        }
    
    }
    package com.li.web;//package com.li.web;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
    
    public class CredentialsMatcher extends SimpleCredentialsMatcher {
    
        Logger logger = LogManager.getLogger(CredentialsMatcher.class);
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
            UsernamePasswordToken utoken=(UsernamePasswordToken) token;
            //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
            String inPassword = new String(utoken.getPassword());
            logger.warn(inPassword);
            //获得数据库中的密码
            String dbPassword=(String) info.getCredentials();
            logger.warn(dbPassword);
            //进行密码的比对
            return this.equals(inPassword, dbPassword);
        }
    
    }
    package com.li.web;
    
    import com.li.web.CredentialsMatcher;
    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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    
    /**
     * shiro的配置类
     * @author Administrator
     *
     */
    @Configuration
    public class ShiroConfiguration {
        @Bean(name="shiroFilter")
        public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
            ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
            bean.setSecurityManager(manager);
            //配置访问权限
            LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
            filterChainDefinitionMap.put("/loginUser", "anon");
            filterChainDefinitionMap.put("/logOut*","logout");
            filterChainDefinitionMap.put("/visitor/*", "anon");  //游客资源
    
            filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
    //        filterChainDefinitionMap.put("/*.*", "authc");
            //配置登录的url和登录成功的url
            bean.setLoginUrl("/login");  //校验不通过,就返回/login
            bean.setSuccessUrl("/home");
            //未授权界面;
            bean.setUnauthorizedUrl("/403");
    
            bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return bean;
        }
        //配置核心安全事务管理器
        @Bean(name="securityManager")
        public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
            System.err.println("--------------shiro已经加载----------------");
            DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
            manager.setRealm(authRealm);
            return manager;
        }
        //配置自定义的权限登录器
        @Bean(name="authRealm")
        public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
            AuthRealm authRealm=new AuthRealm();
            authRealm.setCredentialsMatcher(matcher);
            return authRealm;
        }
        //配置自定义的密码比较器
        @Bean(name="credentialsMatcher")
        public CredentialsMatcher credentialsMatcher() {
            return new CredentialsMatcher();
        }
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
            return new LifecycleBeanPostProcessor();
        }
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
            creator.setProxyTargetClass(true);
            return creator;
        }
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
            AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(manager);
            return advisor;
        }
    }

    8:springboot启动类

         

    package com.li;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;
    
    @EnableAutoConfiguration
    @SpringBootApplication
    @MapperScan(value = "com.li.dao.Mapper")
    public class SpringBootShrioApplication {
        public static void main(String[] args){
            SpringApplication.run(SpringBootShrioApplication.class, args);
        }
    }

    9:在application.yml中配置springboot

    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/shrio
        username: root
        password: 1367356
      devtools:
        restart:
          enabled: true
    
    mybatis:
      mapper-locations: classpath:mybatis/mapper/*.xml   #Mapper所在的配置文件路径,进行扫描
      config-location: classpath:mybatis/mybatis-config.xml  # mybaits-config文件
    #  type-aliases-package: com.liyafei.dao.pojo  # pojo所在的包,与表一一对应

    10:配置mybatis的xml文件

    mybatis-config.xml

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

    UserMapper.xml

    <?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.li.dao.Mapper.UserMapper">
        <resultMap type="com.li.dao.pojo.User" id="userMap">
            <id property="uid" column="uid"/>
            <result property="username" column="username"/>
            <result property="password" column="password"/>
            <collection property="roles" ofType="com.li.dao.pojo.Role">
                <id property="rid" column="rid"/>
                <result property="rname" column="rname"/>
                <collection property="modules" ofType="com.li.dao.pojo.Module">
                    <id property="mid" column="mid"/>
                    <result property="mname" column="mname"/>
                </collection>
            </collection>
        </resultMap>
        <select id="findByUserName" parameterType="string" resultMap="userMap">
            SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid
            inner join role r on r.rid=ur.rid
            inner join module_role mr on mr.rid=r.rid
            inner join module m on mr.mid=m.mid
            WHERE username=#{username};
        </select>
    </mapper>

    11:配置log4j2 http://www.cnblogs.com/liyafei/p/8341885.html

    12 在resource/static目录下配置静态资源html文件,和 ShiroConfiguration.java中配置的应该对应。

         无需注册就能访问的放在visitor目录下,login.html

      对应

    filterChainDefinitionMap.put("/visitor/*", "anon");  //游客资源
    
    
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta charset="UTF-8"/>
    <title>Insert title here</title>
    </head>
    <body>
    <h1>欢迎登录!${user.username }</h1>
    <form action="../loginUser" method="get">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="submit" value="提交">
    </form>
    </body>
    </html>

    需要注册才能访问的放到其它目录下,例如user目录下的index.html

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

    13:启动spring boot,访问任意非游客资源,例如 http://localhost:8080/loginUser

          跳转到登录页面。

       

    输入用户名hlhdidi和密码123 点击提交

    验证通过,跳转到index.html

     14:系统结构图

         

















  • 相关阅读:
    SQL处理重复数据
    ASP.NET下载网站上的地图图片(精)
    js应用大全
    vs2003运行过程中出现的一些错误汇总
    Google卫片下载(转)
    JS获取网页中HTML元素的几种方法
    8位QQ大放送
    .net 读取Xml文件并进行DropDownList数据绑定
    C# Stream 和 byte[] 之间的转换
    【C#4.0】中的dynamic与var的区别
  • 原文地址:https://www.cnblogs.com/liyafei/p/8707310.html
Copyright © 2011-2022 走看看