Java方向(SSM+SpringBoot)项目实训Day14-SpringBoot(新闻管理系统)shiro配置+权限管理+微服务

Day14-SpringBoot(新闻管理系统)shiro配置+权限管理+微服务


Java方向(SSM+SpringBoot)项目实训
Day14(2020.8.4)

shiro配置

安全框架:
shiro对比spring security,更加简易,容易上手,轻巧灵活,实用;
spring security则太庞大、复杂。

利用shiro做一个简单的角色权限管理:
页面不做角色管理模块,而是对数据库中一个表进行添加;
1.po下创建Role实体类;
在这里插入图片描述
Role中添加:

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


    private static final long serialVersionUID = -2608765352170228939L;

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

2.修改User实体类;
User中添加:

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

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

3.po下创建Permission实体类;
在这里插入图片描述
Permission中添加:

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

    private static final long serialVersionUID = -6266065191284242266L;

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

4.shiro请求realm里存有安全的数据源进行认证授权,pom.xml导入shiro所需要的依赖;
pom.xml中添加:

        <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>

然后点击右侧边栏Maven中的刷新,进行下载添加所需要的shiro依赖;

5.实体类Role和Permission中的Id序列化设置;
File→Settings→
在这里插入图片描述
→Apply;
实体类Role中;
在这里插入图片描述
并且添加Getter方法;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

在这里插入图片描述
实体类Permission中,重复上述方法对其Id进行序列化;

6.news下创建realm包下创建NewsRealm类;
在这里插入图片描述
NewsRealm中添加:

public class NewsRealm extends AuthorizingRealm {

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

    @Autowired
    private UserService userService;

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

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

7.news下创建ShiroConfiguration类;
在这里插入图片描述
ShiroConfiguration中添加:

@Configuration
public class ShiroConfiguration {

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

    //创建安全管理器
    @Bean
    public SecurityManager securityManager(NewsRealm realm){
        //使用默认的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        //将自定义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/**","authc");

        shiroFilterFactory.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactory;
    }


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

}

8.注释掉interceptor下的两个实现登录拦截的类,改用shiro安全框架代替;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.修改LoginController类中的login方法;
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";
        }
    }

Test
1.输入错误的密码,登录失败;
在这里插入图片描述
在这里插入图片描述
2.不登录尝试直接输入地址跳转,跳转失败,返回登录界面,即登录拦截成功;
在这里插入图片描述
在这里插入图片描述
Filter过滤器类型:
在这里插入图片描述
在这里插入图片描述

权限管理

1.数据库中如下表中事先插入测试数据;
t_user:
在这里插入图片描述
t_role:
在这里插入图片描述
t_permission:
在这里插入图片描述
t_role_permissions:
在这里插入图片描述
t_user_roles:

在这里插入图片描述
2.修改ShiroConfiguration类中的shiroFilterFactoryBean方法;
shiroFilterFactoryBean方法中添加:

    //配置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/news","perms[user-news]");
        filterMap.put("/admin/types","perms[user-types]");
        filterMap.put("/admin/tags","perms[user-tags]");
        filterMap.put("/admin/login","anon");
        filterMap.put("/admin/**","authc");

        //设置过滤器
        shiroFilterFactory.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactory;
    }

Test
1.全权限管理登录(新闻编辑+分类管理+标签管理);
在这里插入图片描述
新闻、分类、标签均跳转无误;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.分类权限管理登录(分类管理);
在这里插入图片描述
分类跳转无误,新闻、标签则跳转至登录页面;
在这里插入图片描述
在这里插入图片描述

3.标签权限管理登录(标签管理);
在这里插入图片描述
标签跳转无误,新闻、分类则跳转至登录页面;
在这里插入图片描述
在这里插入图片描述

微服务(Spring Cloud)

集中式:
在这里插入图片描述
分布式:
在这里插入图片描述
微服务:
特点:
单一职责、自治

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

Provider Module

1.IDEA创建provider Module(Spring Cloud)步骤如下;
File→New→Module…
在这里插入图片描述
→Spring Initializr→Next
在这里插入图片描述
→修改Group、Artifact、Java Version→Next
在这里插入图片描述
→选择如下依赖→Next
在这里插入图片描述
项目上级目录新建一个scloud文件夹,并修改root、location如下;
在这里插入图片描述
在这里插入图片描述
创建成功如下;
在这里插入图片描述
2.修改pom.xml文件;
pom.xml中添加:

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.0.4</version>
</dependency>

3.创建如下包结构,并修改application.properties文件为application.yml文件;在这里插入图片描述
4.po下创建User实体类;
在这里插入图片描述
User中添加:

@Table(name = "tb_user")
public class User  implements Serializable {

    private static final long serialVersionUID = -1203619350515120953L;

    @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;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", birthday=" + birthday +
                ", created=" + created +
                ", updated=" + updated +
                '}';
    }
}

5.创建数据库sp_learn并在其中创建表tb_user以及插入一条测试数据;
在这里插入图片描述
在这里插入图片描述
6.mapper下创建UserMapper接口;
在这里插入图片描述
UserMapper中添加:

@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User> {
}

7.service下创建UserService类;
在这里插入图片描述
UserService中添加:

@Service
public class UserService {

    @Autowired(required = false)
    private UserMapper userMapper;
    
    public User queryById(Long id){
        return this.userMapper.selectByPrimaryKey(id);
    }

}

8.controller下创建UserController类;
UserController中添加:

@RestController
@RequestMapping("user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id){
        return this.userService.queryById(id);
    }
}

9.修改application.yml文件;
application.yml中添加:

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sp_learn?useSSl=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: ******
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  type-aliases-package: com.roger.service.provider.po

Test
启动ProviderApplication;
在这里插入图片描述

成功抓取到数据库中的user信息;
在这里插入图片描述

Consumer Module

1.创建consumer Module;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.创建如下包结构,并修改application.properties文件为application.yml文件;
在这里插入图片描述

修改application.yml文件;
application.yml中添加:

server:
  port: 80

3.po下创建User实体类;
在这里插入图片描述
User中添加:

public class User  implements Serializable {

    private static final long serialVersionUID = -1203619350515120953L;


    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;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", birthday=" + birthday +
                ", created=" + created +
                ", updated=" + updated +
                '}';
    }
}

4.controller下创建UserController类;
在这里插入图片描述
UserControlle中添加:

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

}

5.修改ConsumerApplication类;
ConsumerApplicatione中添加:

    //注册RestTemplate
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

Test
启动ConsumerApplication;
在这里插入图片描述

成功抓取到数据库中的user信息;
在这里插入图片描述

EurekaServer

在这里插入图片描述
1.创建eureka Module;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.修改application.properties文件为application.yml文件,并在其中添加;
application.yml中添加:

server:
  port: 10086

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

3.修改EurekaApplication类添加一个声明;
在这里插入图片描述
EurekaApplication中添加:

@EnableEurekaServer //声明当前springboot应用是一个eureka服务中心

Test
启动EurekaApplication;
在这里插入图片描述
进入Eureka管理页面,注册服务成功;
在这里插入图片描述
4.provider Module中修改pom.xml文件;
pom.xml中添加:
在这里插入图片描述

<!-- Eureka客户端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

5.provider Module中修改application.yml文件;
application.yml中添加:
在这里插入图片描述

  application:
    name: service-provider #应用名称,注册到eureka后的服务名称
    
eureka:
  client:
    service-url: #EurekaServer 地址
      defaultZone: http://localhost:10086/eureka

6.修改ProviderApplication类添加一个声明;
在这里插入图片描述
ProviderApplication中添加:

@EnableEurekaClient

Test
启动ProviderApplication;
在这里插入图片描述
再次进入Eureka管理界面,新增注册provider服务成功;
在这里插入图片描述

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页