欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springboot+thymeleaf+shiro标签的实例

程序员文章站 2022-03-08 15:29:33
目录1、pom中加入依赖2、用户-角色-权限的表关系3、编写shiro核心类4、登录控制器5、thymeleaf页面权限控制6、标签说明1、pom中加入依赖<...

1、pom中加入依赖

	<dependency>
			<groupid>org.springframework.boot</groupid>
			<artifactid>spring-boot-starter-thymeleaf</artifactid>
			<version>1.5.6.release</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
		<dependency>
			<groupid>org.thymeleaf</groupid>
			<artifactid>thymeleaf</artifactid>
			<version>${thymeleaf.version}</version>
		</dependency>
        <!-- shiro安全框架 -->
		<dependency>
			<groupid>org.apache.shiro</groupid>
			<artifactid>shiro-spring</artifactid>
			<version>1.4.0</version>
		</dependency>
		<!--thymeleaf-shiro-extras-->
		<dependency>
			<groupid>com.github.theborakompanioni</groupid>
			<artifactid>thymeleaf-extras-shiro</artifactid>
			<version>1.2.1</version>
		</dependency>

2、用户-角色-权限的表关系

//用户表
public class user {
    private integer userid;
    private string username;
    private set<role> roles = new hashset<>();
}
//角色表
public class user {
    private integer id;
    private string role;
    private set<module> modules = new hashset<>();
    private set<user> users = new hashset<>();
}
//权限表
public class module {
    private integer mid;
    private string mname;
    private set<role> roles = new hashset<>();
}
    
    
//用户查询
<resultmap id="baseresultmap" type="com.lanyu.common.model.user" >
    <id column="user_id" property="userid" jdbctype="integer" />
    <result column="user_name" property="username" jdbctype="varchar" />
    <!-- 多对多关联映射:collection -->
    <collection property="roles" oftype="role">
      <id property="id" column="c_id" />
      <result property="role" column="role" />
      <collection property="modules" oftype="module">
        <id property="mid" column="mid"/>
        <result property="mname" column="mname"/>
      </collection>
    </collection>
  </resultmap>
  
//查询用户信息,返回结果会自动分组,得到用户信息
  <select id="selectbyphone" resultmap="baseresultmap" parametertype="java.lang.string" >
    select
	  u.*, r.*, m.*
    from
        sys_user u
    inner join sys_user_role ur on ur.userid = u.user_id
    inner join sys_role r on r.rid = ur.roleid
    inner join sys_role_module mr on mr.rid = r.rid
    inner join sys_module m on mr.mid = m.mid
    where
	  u.user_name=#{username} or u.phone=#{username};
  </select>

3、编写shiro核心类

@configuration
public class shiroconfiguration {
    
    //用于thymeleaf模板使用shiro标签
    @bean
    public shirodialect shirodialect() {
        return new shirodialect();
    }
    @bean(name="shirofilter")
    public shirofilterfactorybean shirofilter(@qualifier("securitymanager") securitymanager manager) {
        shirofilterfactorybean bean=new shirofilterfactorybean();
        bean.setsecuritymanager(manager);
        //配置登录的url和登录成功的url
        bean.setloginurl("/loginpage");
        bean.setsuccessurl("/indexpage");
        //配置访问权限
        linkedhashmap<string, string> filterchaindefinitionmap=new linkedhashmap<>();
//        filterchaindefinitionmap.put("/loginpage*", "anon"); //表示可以匿名访问
        filterchaindefinitionmap.put("/admin/*", "authc");//表示需要认证才可以访问
        filterchaindefinitionmap.put("/logout*","anon");
        filterchaindefinitionmap.put("/img/**","anon");
        filterchaindefinitionmap.put("/js/**","anon");
        filterchaindefinitionmap.put("/css/**","anon");
        filterchaindefinitionmap.put("/fomts/**","anon");
        filterchaindefinitionmap.put("/**", "anon");
        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;
    }
}
— - - -- - -- - -- - -- - - -- - - - -- 
public class authrealm extends authorizingrealm {
    @autowired
    private userservice userservice;
    //认证.登录
    @override
    protected authenticationinfo dogetauthenticationinfo(authenticationtoken token) throws authenticationexception {
        usernamepasswordtoken utoken=(usernamepasswordtoken) token;//获取用户输入的token
        string username = utoken.getusername();
        user user = userservice.selectbyphone(username);
        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.getrolelist();
        simpleauthorizationinfo info=new simpleauthorizationinfo();
        list<string> listrole = new arraylist<>();
        if(roles.size()>0) {
            for(role role : roles) {
                if(!listrole.contains(role.getrole())){
                    listrole.add(role.getrole());
                }
                set<module> modules = role.getmodules();
                if(modules.size()>0) {
                    for(module module : modules) {
                        permissions.add(module.getmname());
                    }
                }
            }
        }
        info.addroles(listrole);                       //将角色放入shiro中.
    info.addstringpermissions(permissions);         //将权限放入shiro中.
        return info;
    }
}
//自定义密码比较器
public class credentialsmatcher extends simplecredentialsmatcher {
    private  logger logger = logger.getlogger(credentialsmatcher.class);
    @override
    public boolean docredentialsmatch(authenticationtoken token, authenticationinfo info) {
        usernamepasswordtoken utoken=(usernamepasswordtoken) token;
        //所需加密的参数  即  用户输入的密码
        string source = string.valueof(utoken.getpassword());
        //[盐] 一般为用户名 或 随机数
        string salt = utoken.getusername();
        //加密次数
        int hashiterations = 50;
        simplehash sh = new simplehash("md5", source, salt, hashiterations);
        string strsh =sh.tohex();
        //打印最终结果
        logger.info("正确密码为:"+strsh);
        //获得数据库中的密码
        string dbpassword= (string) getcredentials(info);
        logger.info("数据库密码为:"+dbpassword);
        //进行密码的比对
        return this.equals(strsh, dbpassword);
    }
}

4、登录控制器

    @requestmapping("/loginuser")
    public string loginuser(string username,string password,httpsession session) {
        usernamepasswordtoken usernamepasswordtoken=new usernamepasswordtoken(username,password);
        subject subject = securityutils.getsubject();
        map map=new hashmap();
        try {
            subject.login(usernamepasswordtoken);   //完成登录
            user user=(user) subject.getprincipal();
            session.setattribute("user", user);
            return "index";
        } catch (incorrectcredentialsexception e) {
            map.put("msg", "密码错误");
        } catch (lockedaccountexception e) {
            map.put("msg", "登录失败,该用户已被冻结");
        } catch (authenticationexception e) {
            map.put("msg", "该用户不存在");
        } catch (exception e) {
            return "login";//返回登录页面
        }
        return map.tostring();
    }

5、thymeleaf页面权限控制

<html lang="zh_cn" xmlns:th="http://www.thymeleaf.org"
	  xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
	  
//作为属性控制
<button  type="button" shiro:authenticated="true" class="btn btn-outline btn-default">
	<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</button>
//作为标签
<shiro:hasrole name="admin">
	<button type="button" class="btn btn-outline btn-default">
		<i class="glyphicon glyphicon-heart" aria-hidden="true"></i>
	</button>
</shiro:hasrole>

6、标签说明

guest标签
  <shiro:guest>
  </shiro:guest>
  用户没有身份验证时显示相应信息,即游客访问信息。
user标签
  <shiro:user>  
  </shiro:user>
  用户已经身份验证/记住我登录后显示相应的信息。
authenticated标签
  <shiro:authenticated>  
  </shiro:authenticated>
  用户已经身份验证通过,即subject.login登录成功,不是记住我登录的。
notauthenticated标签
  <shiro:notauthenticated>
  
  </shiro:notauthenticated>
  用户已经身份验证通过,即没有调用subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。
principal标签
  <shiro: principal/>
  
  <shiro:principal property="username"/>
  相当于((user)subject.getprincipals()).getusername()。
lackspermission标签
  <shiro:lackspermission name="org:create">
 
  </shiro:lackspermission>
  如果当前subject没有权限将显示body体内容。
hasrole标签
  <shiro:hasrole name="admin">  
  </shiro:hasrole>
  如果当前subject有角色将显示body体内容。
hasanyroles标签
  <shiro:hasanyroles name="admin,user">
   
  </shiro:hasanyroles>
  如果当前subject有任意一个角色(或的关系)将显示body体内容。
lacksrole标签
  <shiro:lacksrole name="abc">  
  </shiro:lacksrole>
  如果当前subject没有角色将显示body体内容。
haspermission标签
  <shiro:haspermission name="user:create">  
  </shiro:haspermission>
  如果当前subject有权限将显示body体内容

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。