Spring+Mybatis+Shiro开发权限管理系统

代码地址

https://github.com/erlieStar/studyShiro

JSP标签

JSP页面添加

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
标签名称标签条件(均是显示标签内容)
<shiro:authenticated>登录之后
<shiro:notAuthenticated>不在登录状态时
<shiro:guest>用户在没有RememberMe时
<shiro:user>用户在RememberMe时
<shiro:hasAnyRoles name=”abc,123” >在有abc或者123角色时
<shiro:hasRole name=”abc”>拥有角色abc
<shiro:lacksRole name=”abc”>没有角色abc
<shiro:hasPermission name=”abc”>拥有权限资源abc
<shiro:lacksPermission name=”abc”>没有abc权限资源
<shiro:principal>显示用户身份名称
<shiro:principal property=”username”>显示用户身份中的属性值

Shiro中默认的过滤器

过滤器名称描述
anon可以匿名使用
authc需要认证(登陆)才能使用
logout注销登陆时,完成一定的功能,任何现有的session都会失效,而且任何身份都将会失去关联(在Web应用程序中,RememberMe cookie也将会被删除)

前言

整个项目是在学了开涛大佬博客的基础上搭建起来的,只看到了前16章,因为后面的东西也用不到,我就不重复造轮子了,就梳理一下大佬在GitHub上的shiro-example-chapter16的代码,因为这是一个简单的项目,看完也就理解的差不多了
spring-config-shiro.xml

<!-- 基于Form表单的身份验证过滤器 -->
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
    <!--获取表单中的username字段-->
    <property name="usernameParam" value="username"/>
    <!--获取表单中的password字段-->
    <property name="passwordParam" value="password"/>
    <property name="rememberMeParam" value="rememberMe"/>
    <property name="loginUrl" value="/login"/>
</bean>

<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <!--设置登陆的url,用户没有登陆时跳转到这个url-->
    <property name="loginUrl" value="/login"/>
    <property name="filters">
        <util:map>
            <entry key="authc" value-ref="formAuthenticationFilter"/>
            <entry key="sysUser" value-ref="sysUserFilter"/>
        </util:map>
    </property>
    <property name="filterChainDefinitions">
        <value>
            /login = authc
            /logout = logout
            /authenticated = authc
            /** = user,sysUser
        </value>
    </property>
</bean>

个人理解的项目运行流程(如果有不正确的地方,欢迎指出),首先根据Shiro的Web过滤器,进入/login这个controller中

@Controller
public class LoginController {

    @RequestMapping(value = "/login"    )
    public String showLoginForm(HttpServletRequest req, Model model) {
        String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
        String error = null;
        if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if(exceptionClassName != null) {
            error = "其他错误:" + exceptionClassName;
        }
        model.addAttribute("error", error);
        return "login";
    }

}

这个Controller看起来很奇怪,其实是基于Form表单的身份验证过滤器在起作用,它会获取用户输入的username和password看是否正确,如果正确跳转到上一个路径,否则调用HttpServletRequest中的这个方法

setAttribute("shiroLoginFailure",)

这个设置的是异常的类名,这样在LoginController中通过比较异常名就可以知道是什么原因导致登陆失败了。
如果登陆正确,项目跳到IndexController中的/路径,并且获取权限和菜单信息,跳转到首页,这样就能进行各种操作了。
写自己的Realm是一般继承AuthorizingRealm,重写其中2个方法即可

public class MyRealm extends AuthorizingRealm{

    /**
     * 授权,验证权限时调用
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    }

    /**
     * 认证,登陆时调用
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

    }
}

大佬的项目重写了很多方法,是用来清空缓存的,大佬的程序有个Bug,登陆成功后点击后退键,进入登陆页面后,再次输入用户名和密码一直登陆不上去,因此在我的项目中就没用基于Form表单的身份验证过滤器,而是自己制定了一下登陆成功和失败跳转的页面

项目思路

资源(sys_resource)

名称类型描述
idbigint编号,主键
namevarchar资源名称
typevarchar资源类型
priorityint显示顺序
parent_idbigint父编号
permissionvarchar权限字符串
availablebool是否可用

组织机构(sys_organization)

名称类型描述
idbigint编号,主键
namevarchar组织机构名
priorityint显示顺序
parent_idbigint父编号
availablebool是否可用

用户(sys_user)

名称类型描述
idbigint编号,主键
usernamevarchar用户名
passwordvarchar密码
saltvarchar
availablebool是否可用

角色(sys_role)

名称类型描述
idbigint编号,主键
rolenamevarchar角色名
descriptionvarchar角色描述
availablebool是否可用

用户角色表(sys_user_role)

名称类型描述
idbigint编号,主键
user_idbigint用户ID
role_idbigint角色ID

角色资源表(sys_role_resource)

名称类型描述
idbigint编号,主键
role_idbigint角色ID
resource_idbigint资源ID

我自己写的项目将用户和角色的关系,角色和资源的关系写到一张表中,方便维护,也去掉了很多大佬用的没能理解的东西。在dao层,UserDao处理sys_user这张表,UserRoleDao处理sys_user_role这张表,以此类推,service层也是这种思路。除了新建OrganEntity,ResourceEntity,RoleEntity,UserEntity这4个实体类,还建立了RoleVo,UserVo这2个展示层对象,因为类似如下页面用Vo对象修改和展示比较方便

这里写图片描述

参考博客

为什么要在密码里加盐
[1]https://libuchao.com/2013/07/05/password-salt
SQL注入和XSS
[1]http://www.cnblogs.com/rush/category/339662.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java识堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值