SpringBoot新闻管理系统——shiro+SpringCloud微服务

1 shiro

shiro是一个安全框架,其主要功能如下

Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
  Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
  从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
  Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

1.1 数据库设计

根据管理功能划分为三个权限,创建permission表并填入如下内容
在这里插入图片描述

对应的,有三种角色,负责不同的权限范围
在这里插入图片描述
在user中创建三个管理员角色
在这里插入图片描述
在user_roles表中指定用户的角色
在这里插入图片描述

1.2 实体类编写

在编写实体类后就可以直接生成相应的数据库了:

Role

@Entity
@Table(name = "t_role")
public class Role implements Serializable {


    private static final long serialVersionUID = -460222871362844049L;
    @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<com.zr0726.news.po.Permission> permissions=new HashSet<>(0);

User
加上权限和角色:都用集合来存放

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

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

Permission:
按照数据库设计的来。

@Entity
@Table(name="t_permission")
public class Permission implements Serializable {

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

1.3 编写realm

如上所述,相当于dao层废弃掉之前的login方法。
将用户信息存放在token中,我们在验证登录时要将其从token中取出,然后进行验证。

public class NewsRealm extends AuthorizingRealm {
    public void setName(String name){setName("newsRealm");}

    @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.4 编写配置类

主要是告诉shiroRealm、过滤器所在的项目位置。


@Configuration
public class ShiroConfiguration {
    //创建realm
    @Bean
    public NewsRealm getRealm(){return new NewsRealm();}

    @Bean
    public SecurityManager securityManager(NewsRealm realm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(realm);
        return securityManager;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactory=new ShiroFilterFactoryBean();
        shiroFilterFactory.setSecurityManager(securityManager);
        //通用配置
        shiroFilterFactory.setLoginUrl("/admin");
        shiroFilterFactory.setUnauthorizedUrl("/admin");

        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/admin/login","anon");
        filterMap.put("/admin/**","authc");

        shiroFilterFactory.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactory;
    }
    //开启注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

1.5 在web层调用登录服务。

public class LoginController {
    @Autowired
    private UserService userService;

    @GetMapping
    public String loginPage(){
        return "admin/login";
    }

    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password,
                        HttpSession session, RedirectAttributes attributes){


        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";
        }
    }

    @GetMapping("/logout")
    public String logout(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/admin";
    }

2 微服务 SpringCloud

特点有:单一职责、高度自治。

组件有:

  • Eureka:服务治理组件,包含了服务注册中心,服务注册于发现机制的实现
  • Zuul:网关组件
  • Ribbon:负载均衡
  • Feign:服务调用
  • Hystrix:容错管理组件

下面写一个Eureka组件的项目

2.1 项目新建

新建项目
在这里插入图片描述
在这里插入图片描述
添加依赖如下:
在这里插入图片描述
新建一个文件夹,取该模块名字为provider
在这里插入图片描述
在项目中导入依赖包
在这里插入图片描述

2.2 构建项目骨架

在这里插入图片描述

2.3 编写实体类


@Table(name = "tb_user")
public class User implements Serializable {
    private static final long serialVersionUID = 4374725483383661051L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private Integer sex;
    private Date birthday;
    private Date created;
    private Date updated;

配置与实体类对应的数据库:
在这里插入图片描述

2.4 编写服务层和web层

service:

@Service
public class UserService {
    @Autowired(required = false)
    private UserMapper userMapper;

    public User queryById(Long id){
        return this.userMapper.selectByPrimaryKey(id);
    }
}

controller:


@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id){
        return this.userService.queryById(id);
    }
}

运行之后可以从数据库中查询到用户信息。

2.5 编写消费者

由于可以用其他服务来查询信息,可以省去对数据库的操作
在这里插入图片描述
直接在项目中就可以查询到用户信息


@Controller
@RequestMapping("consumer/user")
public class UserController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping
    @ResponseBody
    public User queryById(@RequestParam("id") Long id){
        User user = this.restTemplate.getForObject("http://localhost:8081/user/"+id,User.class);
        return user;
    }
}

接下来写注册中心。注册中心定期更新服务列表,客户消费者定期拉取注册中心中已经注册的服务。
在这里插入图片描述
配置application文件

server:
  port: 10086
spring:
  application:
    name: eureka-server #应用名称,会在Eureka中显示
eureka:
  client:
    service-url: #eurekaserver的地址,现在是自己的地址,如果是集群,需要加上其他server地址
      defaultZone: http://localhost:${server.port}/eureka

声明当前项目是一个注册中心

@SpringBootApplication
@EnableEurekaServer  //声明当前springboot应用是一个eureka服务中心
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }

}

可以进入注册中心管理界面
在这里插入图片描述
可以看到注册到的服务
在这里插入图片描述
接下来把刚刚创建的provider也注册进服务:

server:
  port: 8081

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  application:
    name: service-provider

再次启动注册中心可以看到provider已经被注册进去了。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值