360SDN.COM

首页/Java/列表

Shiro 数据库的权限认证

来源:猿猴家族  2017-09-11 11:17:37    评论:0点击:

    今天整体研究了一下数据库的权限认证.根据网上相应的信息和配置.经过不断的测试.成功了.

    笔记地址:http://122a7d45.wiz03.com/share/s/0iaDR51-QAIy24Yfu80InEPl3JWFXI170AIG2g_5r20EXvLZ

前言:

    作为Shiro一款安全框架来说.相对于SpringSecurity来说简单了不说.虽然我还没有完全的去搞过SpringSecurity.

    首先.其实Shiro并不处理数据库的结构.所有的结构都是程序员自己写的.也就是代表了所有的东西其实都是由程序员管理.而根据我的这一段时间看来.其实应该就是从数据库中获取用户信息 角色信息 权限信息.然后获取到相应的集合对象来实现的.

    而所有的处理逻辑的过程都是写在用户自定义的Realm当中.然后每次进行一个登陆的操作或者其他的一些操作的时候都会从这里经过.读取相应的数据库数据.当然为了提高数据库的效率.还需要加上数据库的缓存.这样在进行一些反复的查询的过程总直接从缓存中读取过来,而不用反复的读取数据库了.

    

步骤:

    1.数据库设计:

    首先进行数据库设计.这一步是后面所有的关键.如果这一步没有完成.后面的一切都是有问题.

    我这里设计的表只有五个.首先是users表.存放对应的用户信息.比如说密码等等.其次是role表.那么role表中存放的是管理员或者普通用户或者其他什么的用户.再其次就是permission.因为如果你需要细化相应的权限的时候.仅仅依靠role表后期维护起来是非常的痛苦的.所以需要在添加一个权限表.比如:"user:update".这么一个数据.这样到时候就可以动态添加用户和用户绑定的权限.下面是具体的数据库结构.

    我新建了一个shiro表.

这里就是我们具体的表.那么中间表的作用就是起到连接两个表的作用.它一般只有两个字段.都是各自对应的两个表的主键.

    下面就是表的具体的相应的结构.

    user表结构

    role表

    permission表

    users_role表

    role_permisson表

    

这样数据库的设计就完成了.我们写了三个最基本的表.那么下面就是如何在shiro中调用这几张表了.

    Shiro设置:

    我采用的IDE是idea.使用的maven工程.前面的一些基本步骤不说了.我这次采用的mybatis SpringMVC Spring Shiro 这么一个结构.只放和shiro相应的重要内容.

    第一 首先是pom,xml当中的内容.

     

  1. <dependency>

  2.            <groupId>org.apache.shiro</groupId>

  3.            <artifactId>shiro-web</artifactId>

  4.            <version>1.2.2</version>

  5.        </dependency>

  6.        <dependency>

  7.            <groupId>org.apache.shiro</groupId>

  8.            <artifactId>shiro-core</artifactId>

  9.            <version>1.2.2</version>

  10.        </dependency>

  11.        <dependency>

  12.            <groupId>org.apache.shiro</groupId>

  13.            <artifactId>shiro-spring</artifactId>

  14.            <version>1.2.2</version>

  15.        </dependency>

 导入shiro的web包核心包和Spring的包.

    第二 在web.xml 中配置shiro的过滤器

  1. <filter>

  2.        <filter-name>shiroFilter</filter-name>

  3.        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

  4.        <init-param>

  5.            <param-name>targetFilterLifecycle</param-name>

  6.            <param-value>true</param-value>

  7.        </init-param>

  8.    </filter>

  9.    <filter-mapping>

  10.        <filter-name>shiroFilter</filter-name>

  11.        <url-pattern>/*</url-pattern>

  12.    </filter-mapping>

 注意这个过滤器必须要在第一个.否则有可能有会出现异常.

    第三 自定义自己的realm

  1. package com.realm;

  2. import com.entity.RolesPermissionsFkKey;

  3. import com.entity.UserRoles;

  4. import com.entity.Users;

  5. import com.entity.UsersRolesFkKey;

  6. import com.mapper.*;

  7. import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;

  8. import org.apache.shiro.SecurityUtils;

  9. import org.apache.shiro.authc.AuthenticationException;

  10. import org.apache.shiro.authc.AuthenticationInfo;

  11. import org.apache.shiro.authc.AuthenticationToken;

  12. import org.apache.shiro.authc.SimpleAuthenticationInfo;

  13. import org.apache.shiro.authz.AuthorizationInfo;

  14. import org.apache.shiro.authz.SimpleAuthorizationInfo;

  15. import org.apache.shiro.authz.UnauthenticatedException;

  16. import org.apache.shiro.realm.AuthorizingRealm;

  17. import org.apache.shiro.subject.PrincipalCollection;

  18. import org.apache.shiro.subject.Subject;

  19. import org.springframework.beans.factory.annotation.Autowired;

  20. import java.lang.reflect.Array;

  21. import java.util.ArrayList;

  22. import java.util.Arrays;

  23. import java.util.Collections;

  24. /**

  25. * Created by hdy on 2017/6/10.

  26. */

  27. //AuthenticationException

  28. public class LoginRealm extends AuthorizingRealm {

  29.    @Autowired

  30.    private UsersMapper userMapper;

  31.    @Autowired

  32.    private RolesPermissionsFkMapper rolesPermissionsFkMapper;

  33.    @Autowired

  34.    private UsersRolesFkMapper usersRolesFkMapper;

  35.    @Autowired

  36.    private UserRolesMapper userRolesMapper;

  37.    @Autowired

  38.    private RolesPermissionsMapper rolesPermissionsMapper;

  39.    //添加相应的用户权限

  40.    @Override

  41.    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

  42.        String username = (String) principalCollection.getPrimaryPrincipal();

  43.        System.out.println("权限认证获取的用户名:" + username);

  44. //        Users users = userMapper.getUsersByUsername(username);

  45.        Users users = userMapper.getUsersByUsernameAndPassword(username, "123");

  46.        ArrayList<UsersRolesFkKey> user = usersRolesFkMapper.getRolesByUser(users.getId());

  47.        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

  48.        ArrayList<String> roles = new ArrayList<String>();

  49.        ArrayList<String> permissions = new ArrayList<String>();

  50.        for (int i = 0; i < user.size(); i++) {

  51.            UsersRolesFkKey key = user.get(i);

  52.            Long id = key.getrId();

  53.            UserRoles role = userRolesMapper.selectByPrimaryKey(id);

  54.            String name = role.getRoleName();

  55.            System.out.println(name);

  56.            roles.add(name);

  57.            ArrayList<RolesPermissionsFkKey> role1 = rolesPermissionsFkMapper.getPermissionByRole(id);

  58.            for (int j = 0; j < role1.size(); j++) {

  59.                RolesPermissionsFkKey rolesPermissionsFkKey = role1.get(j);

  60.                Long getpId = rolesPermissionsFkKey.getpId();

  61.                String permission = rolesPermissionsMapper.selectByPrimaryKey(getpId).getPermission();

  62.                permissions.add(permission);

  63.            }

  64.        }

  65.        info.addRoles(roles);

  66.        info.addStringPermissions(permissions);

  67.        return info;

  68.    }

  69.    //判断用户是否登录成功

  70.    @Override

  71.    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

  72.        String password = new String((char[]) authenticationToken.getCredentials());

  73.        String username = (String) authenticationToken.getPrincipal();

  74.        Users user = userMapper.getUsersByUsernameAndPassword(username, password);

  75.        if (user == null) {

  76.            //说明当前用户不存在

  77.            throw new AuthenticationException("用户名或密码错误");

  78.        }

  79.        AuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());

  80.        return info;

  81.    }

  82. }

 看上去写的挺复杂的.其实逻辑还是十分的清楚的.我们可以看到.一个方法是判断用户登录是否成功的.而另外一个是给登录成功的用户添加相应的身份和权限的.

    首先先配置好相应的mybatis.然后从数据库当中获取相应的角色.获取到相应的角色后在通过角色的主键去获取该角色拥有什么权限.然后都通过SimpleAuthorizationInfo

  1. info.addRoles(roles);

  2. info.addStringPermissions(permissions);

    把相应的角色和权限添加到当中.这个时候.就可以通过getSubject中直接判断是否有相应的权限或者必须的角色啦.后面的事情就是比较简单的了.

    第四 在Spring配置文件中配置shiro

  1. <bean id="loginRealm" class="com.realm.LoginRealm"></bean>

  2.    <!-- 核心,安全管理器 -->

  3.    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

  4.        <!-- 传入相应的realm,如果有多个realm,那么久需要<Realms>标签 -->

  5.        <property name="realm" ref="loginRealm"/>

  6.    </bean>

  7.    <!--  生命周期处理器-->

  8.    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

  9.    <!-- 开启安全注解需要的bean -->

  10.    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"

  11.          depends-on="lifecycleBeanPostProcessor"/>

  12.    <!-- 开启安全注解需要的bean -->

  13.    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

  14.        <property name="securityManager" ref="securityManager"/>

  15.    </bean>

  16.    <!-- shiro过滤器 -->

  17.    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

  18.        <property name="securityManager" ref="securityManager"/>

  19.        <property name="loginUrl" value="/login.jsp"/>

  20.        <property name="successUrl" value="/index.jsp"/>

  21.        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>

  22.        <property name="filterChainDefinitions">

  23.            <value>

  24.                /unauthorized.jsp = anon

  25.                /index.jsp = anon

  26.                /loginAction = anon

  27.                /hello = anon

  28.                /*.jar = anon

  29.                /roleDemo = authc,roles[role1]

  30.                /** = authc

  31.            </value>

  32.        </property>

  33.    </bean>

  34.    <!-- 配置数据源 -->

  35.    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">

  36.        <property name="url" value="jdbc:mysql://localhost:3306/shiro"></property>

  37.        <property name="username" value="root"></property>

  38.        <property name="password" value="hzkjzyjsxy"></property>

  39.    </bean>

  40.    <!-- 事务管理器 -->

  41.    <bean id="transactionManager"

  42.          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

  43.        <property name="dataSource" ref="dataSource"></property>

  44.    </bean>

  45.    <!-- sqlSessionFactory  创建工厂对象-->

  46.    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

  47.        <!-- 加载mybatis的配置文件 -->

  48.        <property name="configLocation" value="classpath:mybatis.xml"></property>

  49.        <!-- 数据源 -->

  50.        <property name="dataSource" ref="dataSource"></property>

  51.        <!-- 自动扫描Mapper的配置文件,不用去mybatis配置文件中进行设置了 -->

  52.        <property name="mapperLocations" value="classpath:com/mapper/*Mapper.xml"/>

  53.        <!-- 自动设置对应的Mapper对象名称 比如com.Dog 可以写成Dog-->

  54.        <property name="typeAliasesPackage" value="com.entity"/>

  55.    </bean>

  56.    <!-- 这个是自动扫描对应包下面的mapper对象 -->

  57.    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

  58.        <property name="basePackage" value="com.mapper"/>

  59.    </bean>

主要的配置文件在上面.基本上也就是这样了.

    就是实例化了一些shiro必备的一些类啊.什么的.反正都是这么写.也没什么好说的了.

    下面是具体的演示.界面写的很简陋.不过功能实现了.

    

    不同的用户登录[wang],拥有角色2.

    hong登录

    wang登录

如果没有权限.看下面:

    通过上面的实验.基本上可以看出.通过数据库用户表和角色表和权限表能够有效的细粒化权限.可以为后期的很多应用后台做服务.

    纯手打......看完的点个赞!说明你看完了.....

阅读原文

为您推荐

友情链接 |九搜汽车网 |手机ok生活信息网|ok生活信息网|ok微生活
 Powered by www.360SDN.COM   京ICP备11022651号-4 © 2012-2016 版权