基于spring-security框架的权限控制+注解方式设置权限

一般需要4张基础表和3张对应关系表。

菜单表 对应角色关系用Set表示:
/**
 * 菜单
 */
public class Menu implements Serializable {
    private Integer id;
    private String name;  //菜单名称
    private String linkUrl;  //访问路径
    private String path;  //菜单项对应的路由路径
    private Integer priority;  //优先级排序
    private String description;  //描述
    private String icon;  //图标
    private Set<Role> roles = new HashSet<Role>(0);  //角色集合
    private List<Menu> children = new ArrayList<Menu>();  //子菜单集合
    private Integer parentMenuId;  //父菜单Id
}
权限表 对应角色关系用Set表示:
/**
 * 权限
 */
public class Permission implements Serializable {
    private Integer id;
    private String name;
    private String keyword;
    private String description;
    private Set<Role> roles = new HashSet<Role>(0);
}
用户表 对应角色关系用Set表示:
/**
 * 用户
 */
public class User implements Serializable {
    private Integer id;
    private Date birthDay;  //生日
    private String gender;  //性别
    private String username;  //用户名。唯一
    private String password;  //密码
    private String remark;  //备注
    private String station;  //状态
    private String telephone;  //联系电话
    private Set<Role> roles = new HashSet<Role>(0);  //对应角色集合
}
角色表 对应用户,权限和菜单关系用Set表示:
/**
 * 角色
 */
public class Role implements Serializable {
    private Integer id;
    private String name;  //角色名称
    private String keyword;  //角色关键字,用于权限控制
    private String description;  //描述
    private Set<User> users = new HashSet<User>(0);
    private Set<Permission> permissions = new HashSet<Permission>(0);
    private LinkedHashSet<Menu> menus = new LinkedHashSet<Menu>(0);
}

附建表语句:

/*
Navicat MySQL Data Transfer

Source Server         : xuyu
Source Server Version : 50515
Source Host           : localhost:3306
Source Database       : authentic

Target Server Type    : MYSQL
Target Server Version : 50515
File Encoding         : 65001

Date: 2021-06-16 23:08:42
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_menu
-- ----------------------------
DROP TABLE IF EXISTS `t_menu`;
CREATE TABLE `t_menu` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `linkUrl` varchar(255) DEFAULT NULL,
  `path` varchar(255) DEFAULT NULL,
  `priority` varchar(255) DEFAULT NULL,
  `icon` varchar(255) DEFAULT NULL,
  `desc` varchar(255) DEFAULT NULL,
  `parentMenuId` int(11) DEFAULT NULL,
  `level` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_menu
-- ----------------------------
INSERT INTO `t_menu` VALUES ('1', '预约管理', 'ordersettinglist.html', '/3-1', null, null, null, null, '1');
INSERT INTO `t_menu` VALUES ('2', '权限管理', 'permission.html', '/6-1', null, null, null, '1', '1');
INSERT INTO `t_menu` VALUES ('3', '菜单管理', 'menu.html', '/6-1', null, null, null, null, '2');

-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `keyword` varchar(255) DEFAULT NULL,
  `desc` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', '新增检查项', 'CHECKITEM_ADD', null);
INSERT INTO `t_permission` VALUES ('2', '删除检查项', 'CHECKITEM_DELETE', null);

-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `keyword` varchar(255) DEFAULT NULL,
  `desc` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', 'ROLE_ADMIN', null);
INSERT INTO `t_role` VALUES ('2', '用户', 'ROLE_USER', null);

-- ----------------------------
-- Table structure for t_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `t_role_menu`;
CREATE TABLE `t_role_menu` (
  `role_id` int(11) DEFAULT NULL,
  `menu_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_role_menu
-- ----------------------------

-- ----------------------------
-- Table structure for t_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission` (
  `role_id` int(11) DEFAULT NULL,
  `permission_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_role_permission
-- ----------------------------

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) DEFAULT NULL,
  `birthday` varchar(255) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_user
-- ----------------------------

-- ----------------------------
-- Table structure for t_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
  `user_id` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_user_role
-- ----------------------------

导入springsecurity pom坐标:

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.sercurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.sercurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${spring.sercurity.version}</version>
        </dependency>

spring配置文件:

spring-security.xml

需要在先springmvc中导入:<import resource="spring-security.xml"></import>

<beans>

    <!--配置那些资源匿名可以访问(不登录也可以访问)-->
    <!--<security:http security="none" pattern="/pages/**"></security:http>-->
    <security:http security="none" pattern="/login.html"></security:http>
    <security:http security="none" pattern="/css/**"></security:http>
    <security:http security="none" pattern="/img/**"></security:http>
    <security:http security="none" pattern="/js/**"></security:http>
    <security:http security="none" pattern="/plugins/**"></security:http>

    <!--auto-config自动配置,如果设置为true,表示自动应用一些默认配置,比如框架会提供一个默认的登录页面
    use-expressions 是否使用表达式-->
    <security:http auto-config="true" use-expressions="true">
        <!--设置在页面可以通过iframe访问受保护的页面,默认为不允许访问-->
        <security:headers>
            <security:frame-options policy="SAMEORIGIN"></security:frame-options>
        </security:headers>
        <!--配置拦截规则,/**表示拦截所有请求-->
        <!--pattern:描述拦截规则-->
        <!--access:指定所需访问角色或者访问权限-->
        <security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>

        <!--只要认证通过节能访问-->
        <!--<security:intercept-url pattern="/index.jsp" access="isAuthenticated()" />-->
        <!--<security:intercept-url pattern="/a.html" access="isAuthenticated()" />-->
        <security:intercept-url pattern="/pages/**" access="isAuthenticated()" />

        /*********以下可以通过注解设置*************************/

        <!--拥有add权限就能访问-->
        <security:intercept-url pattern="/b.html" access="hasAuthority('add')" />

        <!--拥有ROLE_ADMIN角色节能访问c.htmlyemian-->
        <security:intercept-url pattern="/c.html" access="hasRole('ROLE_ADMIN')" />

        <!--如果我们要使用自己指定的页面作为登录页面,必须配置登录表单-->
        <security:form-login login-page="/login.html"
                             username-parameter="username"
                             password-parameter="password"
                             login-processing-url="/login.do"
                             default-target-url="/index.html"   登录成功默认页面
                             authentication-failure-url="/login.html"/>  登录失败页面
        <!--csrf:对应CsrfFilter过滤器 disabled:是否启用CsrfFilter过滤器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁止-->
        <security:cerf disabled="true"></security:cerf>

        <!--logout:退出登录-->
        <!--logout-url:退出登录操作对应的请求路径-->
        <!--logout-success-url:退出登陆后的跳转页面-->
        <security:logout logiut-url="/logout.do" logout-success-url="/login.html" invalidate-session="true" />    
    </security:http>

    <!--配置认证管理器-->
    <security:authentication-manager>
        <!--配置认证提供者-->
        <security:authentication-provider user-service-ref="userService">
            <!--&lt;!&ndash;配置一个用户,后期需要从数据库查询用户&ndash;&gt;-->
            <!--<security:user-service>-->
                <!--<security:user name="admin" password="{noop}1234" authorities="ROLE_ADMIN"/>-->
            <!--</security:user-service>-->

            <!--指定密码进行加密的对象-->
            <security:password-encoder ref="passwordEncoder"></security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>

    <bean id="userService" class="com.xuyu.service.SpringSecurityUserService"></bean>

    <!--配置密码加密对象-->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoding"/>

    <!--开启spring注解-->
    <context:annotation-config></context:annotation-config>
</beans>

只需要Service实现security框架提供的UserDetailsService接口:

//实现security框架提供的接口
@Compoment
public class SpringSecurityUserService implements UserDetailsService {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    //模拟数据库中的用户信息
    public static Map<String, User> map = new HashMap<String,User>();
    public void initUserData(){
        User user = new User();
        user.setUsername("admin");
        user.setPassword(passwordEncoder.encode("admin"));  //加密

        User user1 = new User();
        user1.setUsername("yuangong");
        user1.setPassword("2123");

        map.put(user.getUsername(),user1);
        map.put(user1.getUsername(),user1);
    }

    //根据用户名查询用户信息
    public UserDetals loadUserByUsername(String username){
        System.out.println("用户输入的用户名为"+username);
        //根据用户名查询数据库获得用户信息(包含数据库中存储的密码信息)
        User user = map.get(username);
        if(user == null){
            //用户不存在
            return null;
        }else {
            //将用户信息返回给框架
            //框架会进行密码比对(页面提交的密码和数据中查询的密码进行比对)
            ArrayList<GrantedAuthority> list = new ArrayList<GrantedAuthority>();  //授权,后期需要查询数据库
            list.add(new SimpleGrantedAuthority("permission_A"));  //授权
            list.add(new SimpleGrantedAuthority("permission_B"));

            if(username.equals("admin")) {  //只有admin才能登录
                list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));  //授予角色
            }
            security.core.userdetails.User securityUser = new security.core.userdetails.User(username,user.getPassword(),list);
            return securityUser;
        }
    }
}

基于方法注解方式进行权限设置:

spring-security.xml  添加注解开关


    <!--开启spring注解-->
    <context:annotation-config></context:annotation-config>

    <mvc:anotation-driven></mvc:anotation-driven>
    <context:component-scan base-package="com.xuyu.controller"></context:component-scan>

    <!--开启方法注解方式权限控制-->
    <security:global-method-security pre-post-annotations="enable" />

 编写测试类

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/add")
    @PreAuthorize("hasAuthority('add')")  //调用此方法要求当前用户必须具有add权限
    public String add(){
        System.out.println("test");
        return "success";
    }

    @RequestMapping("/delete")
    @PreAuthorize("hasRole('ROLE_ADMIN')")  //调用此方法要求当前用户必须具有ROLE_ADMIN角色
    public String delete(){
        System.out.println("delete test");
        return "success";
    }
}

从数据库获取角色和权限信息版本:

实现spring security登录鉴权接口:
//此方法框架会在用户登录时调用
public class SpringSecurityUserService implements UserDetailsService {

    //使用dubbo通过网络远程调用服务提供方获取数据库中的信息

    @Autowired
    private UserSerivice userSerivice;

    //根据用户名查询数据库获取用户信息
    public UserDeails loadUserByUsername(String username){
        User user = userSerivice.findByUsername(username);
        if(user == null){
            return null;
        }
        //动态为当前用户授权
        List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
        Set<Role> roles = user.getRoles();
        for (Role role : roles) {
            //遍历角色集合,为用户授予角色
            list.add(new SimpleGrantedAuthority(role.getKeyword()));
            Set<Permission> permissions = role.getPermissions();
            for (Permission permission : permissions) {
                //遍历权限集合,为用户授权
                list.add(new SimpleGrantedAuthority(permission.getKeyword()));
            }
        }
        org.springframework.security.core.userdetails.User securityUser = new org.springframework.security.core.userdetails.User(username,user.getPassword(),list);
        return securityUser;
    }
}
@Service
@Transactional
public class UserSeriviceImpl implements UserSerivice {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private PermissionDao permissionDao;

    //根据用户名查询数据库获取用户信息,同时需要查询查询角色关联的权限信息
    public User findByUsername(String username){
        User user = userDao.findByUsername(username);  //查询用户基本信息。不包括用户的角色
        if(user == null){
            return null;
        }
        Integer userId = user.getId();
        //根据用户Id查询对应的角色
        Set<Role> roles = roleDao.findByUserId(userId);
        for (Role role : roles) {
            Integer roleId = role.getId();
            //根据角色Id查询关联的权限
            Set<Permission> permissions = permissionDao.findByRolreId(roleId);
            role.setPermissions(permissions);  //角色关联权限
        }
        user.setRoles(roles);  //让用户关联角色
        return user;
    }
}
UserDao.xml
<mapper namespace="com.xuyu.dao.UserDao">
    <select id="findByUsername" parameterType="String" resultType="com.xuyu.pojo.User">
        select * from t_user where username = ${username}
    </select>
</mapper>

RoleDao.xml:
<mapper namespace="com.xuyu.dao.RoleDao">
    <!--根据用户Id查询关联的角色-->
    <select id="findByUserId" parameterType="int" resultType="com.xuyu.pojo.Role">
        select a.* from t_role a,t_user_role b where a.id = b.role_id and b.user_id = #{user_id}
    </select>
</mapper>

PermissionDao.xml
<mapper namespace="com.xuyu.dao.PermissionDao">
    <!--根据用户Id查询关联的角色-->
    <select id="findByRoleId" parameterType="int" resultType="com.xuyu.pojo.Permission">
        select a.* from t_permission a,t_role_permission b where a.id = b.permission_id and b.roleid = #{role_id}
    </select>
</mapper>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值