Shiro中自定义Realm案例

3 篇文章 0 订阅

        之前我们将用户信息放在了shiro.ini中,将用户的信息写si在了上面,并没有与数据库进行关联,因此我们需要自定义Realm,将用户的信息存放在数据库中。

第一步:建表(并添加用户数据)

第二步:建立Maven项目导入依赖:

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- shiro依赖 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.4.0</version>
    </dependency>
    <!-- 日志依赖 -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.12</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.12</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>

    <!-- ============ Servlet ============ -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- ============== SpringMVC ============== -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>

    <!-- lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.4</version>
      <scope>provided</scope>
    </dependency>

    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>

    <!--  AOP  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>

    <!-- spring-jdbc(会传递tx) ,context-support ,aspects-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>

    <!-- spring+mybatis集成依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>

    <!-- MyBatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <!-- mysql驱动 依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.25</version>
      <scope>runtime</scope>
    </dependency>

    <!-- druid依赖 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
    </dependency>
  </dependencies>

第三步:配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--搭建shiro环境
      在项目最外层,构建访问控制层
      在启动时,初始化shir环境-->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!--在项目启动时,加载web-info或classpath下的shiro.ini
  并且构件webSecurityManager,构建所有配置中使用的过滤器链,ShiroFilter会获取此过滤器链-->
  <listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
</web-app>

第四步:编写Dao层(这里只放dao层的xml内容,dao层接口相对简单就不写出来了)

<?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">
        <!--
          dtd:docuemtn type definition  为当前提供约束
             :标签   属性   层级    顺序
          Mapper文件,映射文件,替换DAO实现类
        -->
<mapper namespace="cn.itcast.dao.PermissionDao">

<select id="queryAllPermissionByUsername" parameterType="string" resultType="string">
        select DISTINCT t_permission.permission_name
        from t_user
          JOIN t_user_role ON t_user.id = t_user_role.user_id
          JOIN t_role on t_role.id = t_user_role.role_id
          JOIN t_role_permission ON t_role.id = t_role_permission.role_id
          JOIN t_permission ON t_role_permission.permission_id = t_permission.id
        WHERE t_user.username=#{username}
    </select>

</mapper>

<?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">
<!--
  dtd:docuemtn type definition  为当前提供约束
     :标签   属性   层级    顺序
  Mapper文件,映射文件,替换DAO实现类
-->
<mapper namespace="cn.itcast.dao.RoleDao">

    <select id="queryAllRolenameByUsername" parameterType="string" resultType="string">
        select t_role.role_name
        from t_user
        JOIN t_user_role ON t_user.id = t_user_role.user_id
        JOIN t_role on t_role.id = t_user_role.role_id
        WHERE t_user.username=#{username}
    </select>

</mapper>

<?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">
<!--
  dtd:docuemtn type definition  为当前提供约束
     :标签   属性   层级    顺序
  Mapper文件,映射文件,替换DAO实现类
-->
<mapper namespace="cn.itcast.dao.UserDao">

    <select id="queryUserByUsername" parameterType="string" resultType="cn.itcast.domain.User">
        select id,username,password
        from t_user
        where username = #{username}
    </select>

</mapper>

第五步:编写自定义Realm

package cn.itcast.realm;

import cn.itcast.domain.User;
import cn.itcast.service.PermissionService;
import cn.itcast.service.RoleService;
import cn.itcast.service.UserService;
import cn.itcast.serviceImpl.UserServiceImpl;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.web.context.ContextLoader;

import java.util.Set;

public class MyRealm extends AuthorizingRealm {
    /*查询权限信息
     *何时触发:/user/query=roles["admin"]
     * 查询方式通过用户名查询,该用户的权限,角色信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取当前用户的用户名
        String username=(String)principals.getPrimaryPrincipal();
        RoleService roleService=ContextLoader.getCurrentWebApplicationContext().getBean("roleServiceImpl",RoleService.class);
        PermissionService permissionService=ContextLoader.getCurrentWebApplicationContext().getBean("permissionServiceImpl",PermissionService.class);
        //查询当前用户信息
        Set<String> roles=roleService.queryAllRolenameByUsername(username);
        Set<String> perms=permissionService.queryAllPermissionByUsername(username);
        //将查询出的信息封装
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo(roles);
        simpleAuthorizationInfo.setStringPermissions(perms);
        return simpleAuthorizationInfo;
    }
    /*查询身份信息,
    * 查询方式:通过用户名查询用户信息
    * 何时触发:subject.login(token)
    * 作用:查询身份信息,并返回即可,不用做任何比对
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户登录时发送来的用户名
        String username=(String)token.getPrincipal();
        //查询用户信息
        UserService userService= ContextLoader.getCurrentWebApplicationContext().getBean("userServiceImpl", UserService.class);
        User user=userService.queryUserByUsername(username);
        if(user==null){//不存在用户名
            return null;
        }
        return  new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),this.getName());
    }
}

最后只需要修改我们的realm配置文件即可

[main]
#没有身份认证时,跳转地址
shiro.loginUrl = /user/login
#角色或权限校验不通过时,跳转地址
shiro.unauthorizedUrl=/user/perms/error
#登出后的跳转地址,回首页
shiro.redirectUrl=/
#声明自定义的Realm
realm04=cn.itcast.realm.MyRealm
#将自定义的Realm注册给 核心控制者:Securitymanager
securityManager.realms=$realm04

        整个流程大概就是当有请求发送过来时先经过ShiroFilter然后经过一些列的验证,当通过时去调用Realm去进行验证,当验证用过时继续进行下一步操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值