【学习日记】(SpringBoot-part 9)新闻管理系统—shiro权限管理

新闻管理系统的Shiro权限管理

Shiro权限管理

shiro

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

角色权限管理

  1. 新建权限实体类Permission,实现序列化的接口
@Entity
@Table(name = "t_permission")
public class Permission implements Serializable {

    private static final long serialVersionUID = 6969178802824371390L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
    private Long id;
    private String name;
    private String code;
    private String description;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
  1. 新建角色实体类Role,实现序列化的接口
@Entity
@Table(name = "t_role")
public class Role implements Serializable {

    private static final long serialVersionUID = -1513987909228269210L;//序列id

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
    private Long id;
    private String name;
    private String description;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users = new HashSet<>(0);

    @ManyToMany(fetch = FetchType.EAGER)
    private Set<Permission> permissions = new HashSet<>(0);

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

    public Set<Permission> getPermissions() {
        return permissions;
    }

    public void setPermissions(Set<Permission> permissions) {
        this.permissions = permissions;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", users=" + users +
                ", permissions=" + permissions +
                '}';
    }
}

这里需要添加唯一的一个序列id

File -> Settings -> Editor -> Inspections -> Serialization issues 勾选全部
在这里插入图片描述再在Role类名处Alt+Enter 添加唯一序列,同样在Permission也需要
在这里插入图片描述

在Role新增了和User实体的关系,同样在User中也需要新增和Role的实体关系

    @ManyToMany(fetch = FetchType.EAGER)
    private Set<Role> roles = new HashSet<>(0);
  1. 添加shiro依赖
<dependency>
   	<groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
</dependency>
  1. 新建realm包 -> 新建NewsRealm
public class NewRealm extends AuthorizingRealm {

    public void setName(String name){setName("nameRealm");}

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken)authenticationToken;
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        User user = userService.checkUsers(username,password);
        if(user != null){
            return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
        }
        return null;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取用户认证信息
        User user = (User)principalCollection.getPrimaryPrincipal();
        //构造认证数据
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<Role> roles = user.getRoles();
        for(Role role:roles){
            //添加角色信息
            info.addRole(role.getName());
            for(Permission permission:role.getPermissions()){
                info.addStringPermission(permission.getCode());
            }
        }

        return info;
    }
    
    @Autowired
    private UserService userService;
}
  1. 新建Shiro配置文件ShiroConfiguration(在realm文件夹在同一目录)
@Configuration
public class ShiroConfiguration {

    //创建realm
    @Bean
    public NewRealm getRealm(){return new NewRealm();}

    //创建安全管理器
    @Bean
    public SecurityManager securityManager(NewRealm realm){
        //使用默认的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        return securityManager;
    }

    //配置shiro过滤器工厂
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactory = new ShiroFilterFactoryBean();
        shiroFilterFactory.setSecurityManager(securityManager);
        //通用配置
        shiroFilterFactory.setLoginUrl("/admin");
        shiroFilterFactory.setUnauthorizedUrl("/admin");

        /**
         * key: 请求路径
         * value: 过滤器类型
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        filterMap.put("/admin/login","anon");
        filterMap.put("/admin/**","authc");

        shiroFilterFactory.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactory;
    }

    //开启shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}
  1. 修改LoginController的login方法
    @PostMapping("/login")
    public String login(@RequestParam String username , @RequestParam String password,
                        HttpSession session, RedirectAttributes attributes) {
/**
 *      原来的登陆验证方法

        User user = userService.checkUsers(username, password);
        if (user != null) {
            user.setPassword(null);
            session.setAttribute("user", user);
            return "admin/index";
        } else {
            attributes.addFlashAttribute("message", "用户名或密码错误");
            return "redirect:/admin";
        }
 */
        //使用注册登陆令牌
        try{
            //构造登陆令牌
            UsernamePasswordToken uptoken = new UsernamePasswordToken(username,password);
            //获取subject (主体)
            Subject subject = SecurityUtils.getSubject();
            //登陆  使用令牌
            subject.login(uptoken);
            User user = (User) subject.getPrincipal();
            session.setAttribute("user",user);
            return "admin/index";

        } catch (Exception e) {
            attributes.addFlashAttribute("message","用户名或密码错误");
            return "redirect:/admin";
        }
    }
  1. 测试
    输入admin/下的路径时自动跳转到登陆界面
    在这里插入图片描述在这里插入图片描述

  2. 权限职责分配
    不同的用户负责的模块不一样,例如1用户负责新闻模块、2用户负责分类模块…

    • 在permission数据表中添加职责对应关系
      在这里插入图片描述

    • 在user数据表中添加相应关系
      在这里插入图片描述

    • 在角色和权限中间表中声明对应关系
      在这里插入图片描述

    • 用户和角色关系对应表
      在这里插入图片描述修改ShiroConfiguration
      在这里插入图片描述添加代码

        filterMap.put("/admin/types","perms[user_types]");
        filterMap.put("/admin/news","perms[user_news]");
        filterMap.put("/admin/tags","perms[user_tags]");

便可以实现不同权限的用户只能访问当前权限下的功能模块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值