[java] Shiro 框架学习 (二)Spring Boot 整合

环境

开发工具:IDEA

jdk版本:jdk1.8

创建项目

1.新建spring-boot项目

项目结构:

2.导包 pom.xml文件

添加spring-boot 父级依赖,maven用户可用通过继承parent项目来获得一些合理的默认配置

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

导入spring-boot快速搭建web项目依赖包和集成shiro框架的依赖包 

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>1.5.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>1.5.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-Java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
    </dependencies>

添加spring - boot 支持maven


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

3.配置application.yml 文件,springboot项目所有配置都在该文件中完成

server:
  port: 8082
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
  http:
    encoding:
      charset: utf-8
      enabled: true

4.创建用户,角色,权限实体类,shiro权限控制必须有这个三个实体类(表)

User类


package com.ztwow.springshiro.entity;

import javax.persistence.*;
import java.util.List;

/**
 * user
 * 用户实体类
 *
 * */

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(unique = true)
    private String name;
    private Integer password;
    @OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
    private List<Role> roles;

    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 List<Role> getRoles() {
        return roles;
    }

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

    public Integer getPassword() {
        return password;
    }

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

}




Role类


package com.ztwow.springshiro.entity;

import javax.persistence.*;
import java.util.List;
/**
 * role
 * 角色实体类
 *
 * */

@Entity
public class Role {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String roleName;
    @ManyToOne(fetch = FetchType.EAGER)
    private User user;
    @OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
    private List<Permission> permissions;

    public Long getId() {
        return id;
    }

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

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

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

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



permission类


package com.ztwow.springshiro.entity;


import javax.persistence.*;

/**
 * permission
 * 权限实体类
 *
 * */


@Entity
public class Permission {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String permission;
    @ManyToOne(fetch = FetchType.EAGER)
    private Role role;

    public Long getId() {
        return id;
    }

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

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }



}

 

5. 持久层接口和实现类

使用JPA操作数据库:jpa学习

#baseDao 接口 继承JPA动态查询和分页
package com.ztwow.springshiro.dao;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.io.Serializable;

@NoRepositoryBean
public interface BaseDao<T,I extends Serializable> extends PagingAndSortingRepository<T,I>, JpaSpecificationExecutor<T> {
}


#User 接口 实现baseDao

package com.ztwow.springshiro.dao;

import com.ztwow.springshiro.entity.User;

public interface UserDao extends BaseDao<User,Long>{

    User findByName(String name);
}


#Role 接口实现baseDao

package com.ztwow.springshiro.dao;

import com.ztwow.springshiro.entity.Role;

public interface RoleDao extends BaseDao<Role,Long>{
}

6. 编写业务层接口和实现类

#业务层接口
package com.ztwow.springshiro.service;

import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;

import java.util.Map;

public interface ILoginService {

    User addUser(Map<String,Object> map);

    Role addRole(Map<String,Object> map);

    User findByName(String name);
}


#实现类
package com.ztwow.springshiro.service.impl;

import com.ztwow.springshiro.dao.RoleDao;
import com.ztwow.springshiro.dao.UserDao;
import com.ztwow.springshiro.entity.Permission;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class LoginServiceImlp implements ILoginService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;


    //添加用户
    @Override
    public User addUser(Map<String, Object> map) {
        User user = new User();
        user.setName(map.get("username").toString());
        user.setPassword(Integer.valueOf(map.get("password").toString()));
        userDao.save(user);
        return user;
    }

    //添加角色
    @Override
    public Role addRole(Map<String, Object> map) {

       User user = userDao.findOne(Long.valueOf(map.get("userId").toString()));
       Role role = new Role();
       role.setRoleName(map.get("roleName").toString());
       role.setUser(user);
       Permission permission1 = new Permission();
       permission1.setRole(role);
       permission1.setPermission("create");
       Permission permission2 =new Permission();
       permission2.setPermission("update");
       permission2.setRole(role);
       List<Permission> permissions = new ArrayList<Permission>();
       permissions.add(permission1);permissions.add(permission2);
       role.setPermissions(permissions);
       roleDao.save(role);
       return role;
    }

    //通过用户名查询用户
    @Override
    public User findByName(String name){
        return userDao.findByName(name);
    }

}

7.Shiro自定义配置类,通过@Bean注解的方式代替springMVC的XMl方式配置

package com.ztwow.springshiro.config;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {


    //加入自己的验证方式到容器
    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();

        return myShiroRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,(添加)设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<String, String>();
        //登出
        map.put("/logout","logout");
        //对所有用户认证
        map.put("/**","authc");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
        //首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //加入注解的使用,不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }



}

8. Realml类 用于获取安全数据,给用户添加角色和权限,认证提交的用户是否合法,并通过用户获取安全数据

package com.ztwow.springshiro.config;

import com.ztwow.springshiro.entity.Permission;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 实现AuthorizingRealm接口用户用户认证
 *
 * AuthorizingRealm
 * 授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,
 * 常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限
 * */

public class MyShiroRealm extends AuthorizingRealm {

    //用于用户查询
    @Autowired
    private ILoginService loginService;

    /**
     * 角色权限和对应权限添加
     *
     * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String name = (String) principalCollection.getPrimaryPrincipal();
        //查询用户名称
        User user = loginService.findByName(name);
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        for(Role role:user.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());

            for (Permission permission : role.getPermissions()) {
                //添加权限
                simpleAuthorizationInfo.addStringPermission(permission.getPermission());

            }

        }
        return simpleAuthorizationInfo;
    }

    /***
     * 用户认证
     *
     * */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if(authenticationToken.getPrincipal() == null){
            return  null;
        }

        String name = authenticationToken.getPrincipal().toString();
        User user = loginService.findByName(name);

        if(user == null){

            //用户不存在返回后会报出异常
            return null;
        }else{

            //这里验证authenticationToken和simpleAuthenticationInfo的信息
           SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name,user.getPassword().toString(),getName());
           return simpleAuthenticationInfo;
        }

    }
}

8.Controller类 

package com.ztwow.springshiro.controller;

import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;

@RestController
public class LoginController {

    @Resource
    private ILoginService loginService;

    //退出的时候是get请求,主要是用于退出
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(){
        return "login";
    }

    //post登录
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(@RequestBody Map map){
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                map.get("username").toString(),
                map.get("password").toString());
        //进行验证,这里可以捕获异常,然后返回对应信息
        subject.login(usernamePasswordToken);
        return "login";
    }

    @RequestMapping(value = "/index")
    public String index(){
        return "index";
    }

    //登出
    @RequestMapping(value = "/logout")
    public String logout(){
        return "logout";
    }

    //错误页面展示
    @RequestMapping(value = "/error",method = RequestMethod.POST)
    public String error(){
        return "error ok!";
    }

    //数据初始化
    @RequestMapping(value = "/addUser")
    public String addUser(@RequestBody Map<String,Object> map){
        User user = loginService.addUser(map);
        return "addUser is ok! \n" + user;
    }

    //角色初始化
    @RequestMapping(value = "/addRole")
    public String addRole(@RequestBody Map<String,Object> map){
        Role role = loginService.addRole(map);
        return "addRole is ok! \n" + role;
    }

    //注解的使用
    @RequiresRoles("admin")
    @RequiresPermissions("create")
    @RequestMapping(value = "/create")
    public String create(){
        return "Create success!";
    }


}

主要流程:页面所有的操作请求都会通过subject(代表当前用户),然后将subject绑定到SecurityManager上,由SecurityManager管理有所与subject的交互,当SecurityManager需要验证用户身份是否合法,会通过Realm提供的Authentication和Authorization认证用户获取安全数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值