后台权限管理项目总结

        最近做了一个后台的权限管理项目,没有用到springSecurity,也没有用到shiro,纯粹是用原生态的写法做的,有点粗糙,但是思想没变,这里记录一下自己的心得。

       首先是设计数据库的表,一共5张表,分别为用户表,角色表,权限表,用户角色关系表,角色权限关系表。这里遇到的最大的坑就一个,导致后台程序被大改,这里给自己警醒,场景是这样的,当我手动从数据库中删除一条数据的时候,代码debug调试的时候竟然查到我删掉的数据,这是一件很诡异的事情,后来上网查了一些这方面的资料,虽然没查到我这个问题的原因,但是解决方案算是找到了,即为:一张表除了有一个数据库自带的自增主键,还要设定一个逻辑主键,可以用UUID作为主键。第二个问题是项目中的删除很少用到delete语句,一般都是软删除,即为添加一个字段isDelete(0表示删除,1表示存在),所以删除即为更新一下这个字段即可。

       然后是后台程序方面:第一个肯定是登录操作,判断逻辑还是有点绕的,首先根据用户名查该用户是否存在,如果不存在,即返回给前端错误码和错误信息;如果查到的话,再将查到的用户的密码和前台传过来的密码进行比对,如果不等,那么进行三次机会重新输入,如果都输入错误,则将该用户的状态更新为锁定,表示该用户暂时不能登录;如果该用户密码比对正确或者三次机会中有一次机会输入正确,则表示该用户登陆成功,更新该用户数据库密码错误次数为初始值。然后用该用户主键根据角色用户关系表查询该用户的角色,为一个集合,再用该角色的主键根据角色权限关系表查询该角色的权限信息,为一个list,然后用该用户的唯一标识,比如该用户的编号,拼接一个随机数,生成一个token,然后将该用户信息和权限的list集合以及这个token封装到一个对象中,返给前台,还将这个信息存在redis缓存中,当然还有个自定义的本地缓存,怎么创建,这样来:创建一个工具类,例如LocalCache类,然后在这个类中定义一个static的集合,例如:

                    private static List<缓存存储的对象> myList =  new ArrayList<>();

然后是用户类和角色类的增删改查,删除数据改isDelete状态,修改数据后返回修改后的数据信息,这些没什么好说的,新增数据的时候要注意先查一下,如果数据库中有这条数据的话,那么不让增加。代码需要try{}catch(){},这样出现错误也能够捕捉的到。区别权限的菜单级和按钮级,这个很好区别,根据Controller的@RequestMapping("")中的path很好判断。例如:

然后还有根据日期区间进行查询,例如查询当天的数据,例如查询2018-12-12 00:00:00到2018-12-12 23:59:59这个日期区间的数据,但是前台传给你的只有2018-12-12日这个格式的数据,因此需要你进行转换为你所需要的日期形式,如下:

package com.Jevin.controller;

import org.junit.Test;
import java.util.Calendar;
import java.util.Date;


public class DateUtil {

    /**
     * 获取日期的00:00:00
     * @param startDate
     * @return
     */
    public static Date getStartTime(Date startDate){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        return calendar.getTime();
    }

    /**
     * 获取日期的23:59:59
     * @param endDate
     * @return
     */
    public static Date getEndTime(Date endDate){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        calendar.set(Calendar.HOUR_OF_DAY,23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        return calendar.getTime();
    }

    @Test
    public void test(){
        System.out.println(getEndTime(new Date()));
    }

}

然后就是对象封装的问题,即为同一个类,我们需要将其拆分为三个对象,一个用来接收前台的参数,一个对象用来和数据库进行交互,一个对象用来返回给前端。

然后是过滤器的问题,到目前为止我已经试过4中过滤器了:

第一种是springAOP过滤器:

package com.Jevin.controller;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;


public class PermissionInterceptor implements MethodInterceptor {
    
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("进入过滤器");
        return methodInvocation.proceed();
    }
}

配置文件

<!-- 配置拦截器的bean -->
    <bean id="permissionInterceptor" class="com.Jevin.controller.PermissionInterceptor"/>
    <!-- springAOP方法拦截器配置 -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <value>userController</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>permissionInterceptor</value>
            </list>
        </property>
    </bean>
    <!-- 任意一个类的bean -->
    <bean id="userController" class="com.Jevin.controller.UserController"/>

第二种是jboss.resteasy中的CorsFilter

导入一下依赖

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>3.0.12.Final</version>
</dependency>
package com.Jevin.controller;

import org.jboss.resteasy.plugins.interceptors.CorsFilter;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
@PreMatching
public class PermissionFilter extends CorsFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        System.out.println("requestContext");
        boolean flag = false;
        if(!flag){
            Result result = new Result();
            result.setResponseCode("000");
            result.setReserveMsg("error message");

            Response.ResponseBuilder builder = Response.status(200).entity(result);
            builder.type(MediaType.APPLICATION_JSON);
            requestContext.abortWith(builder.build());
        }

    }
}

 

其中Result是一个结果集对象,主要用来返回给前端响应结果的。

第三种是javax.servlet.Filter中的doFilter()方法过滤器,

第四种是org.springframework.web.servlet.HandlerInterceptor,

这两种比较常见,在网上随处可以查到一大把,这里就不说了。

然后是用户状态,比方说0表示正常,1表示销户,2表示锁定,0,1,2是插入数据库中的数据;正常,销户,锁定是返回给前端的用户状态信息,这里最好用enum枚举类型来做,如下:

package com.Jevin.controller;

public enum UserStateEnum {

    NORMAL("0","正常"),
    CANCEL("1","注销"),
    LOCK("2","锁定");

    private String code;
    private String status;

    UserStateEnum(String code,String status){
        this.code=code;
        this.status=status;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

大致自己所走过的弯路,所总结的也就这些了,希望给道友一些友好的提示。。。

猜你喜欢

转载自blog.csdn.net/boy_chen93/article/details/83177924