Springboot整合shiro做安全框架(一)

shiro是开源安全框架,提供身份认证,授权,会话管理,加密等操作

会话管理:

传统项目是cookie维持会话管理,

前后分离开发是获取shiro的sessionId维持会话,参考:https://blog.csdn.net/u013615903/article/details/78781166/

本此整合默认用cookie管理,参考:https://www.cnblogs.com/asker009/p/9471712.html

1、项目结构

Springboot整合shiro做安全框架(一)_第1张图片

2、引入依赖,依赖涉及了JPA,mybatis、shiro、swagger等,做测试需要的依赖,贴上去



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.3.RELEASE
		 
	
	com.example
	demo-1
	0.0.1-SNAPSHOT
	war
	demo-1
	Demo project for Spring Boot

	
		1.8
		1.2.37
	

	
	
		
		   org.springframework.boot
		   spring-boot-starter-data-jpa
		
		  
	        org.springframework.boot  
	        spring-boot-starter-web  
	          
	              
	                org.springframework.boot  
	                spring-boot-starter-logging  
	              
	          
	     
	     
        
            com.alibaba
            druid-spring-boot-starter
            1.1.10
        
		
			org.springframework.session
			spring-session-core
		
	
		
			org.projectlombok
			lombok
			true
		
			
		
		
		   org.apache.shiro
		   shiro-spring
		   1.4.0
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
        
            javax.servlet
            javax.servlet-api
            provided
        
        
	    
	        org.springframework.boot
	        spring-boot-devtools
	        true
	    
	    
        
            commons-httpclient
            commons-httpclient
            3.1
        
        
        
            javax.servlet
            jstl
        
        
        
            org.springframework.boot
            spring-boot-starter-tomcat
            provided
        
        
          
            org.springframework.boot
            spring-boot-starter-data-redis
         
         
        
        
        
            org.apache.tomcat.embed
            tomcat-embed-jasper
            provided
        
		 
            com.fasterxml.jackson.core
            jackson-core
        
        
            com.fasterxml.jackson.datatype
            jackson-datatype-hibernate5
        
		
		
			org.springframework.boot
			spring-boot-starter-cache
		
		
			net.sf.ehcache
			ehcache
		
        
            org.apache.commons
            commons-lang3
        

        
            commons-cli
            commons-cli
            1.2
        

        
            commons-io
            commons-io
            2.2
        

        
            com.alibaba
            fastjson
            ${fastjson.version}
        
        
        
		    org.mybatis.spring.boot
		    mybatis-spring-boot-starter
		    1.1.1
		
	    
	       
	        org.springframework.boot  
	        spring-boot-starter-log4j2  
	      
	    
			com.spring4all
			spring-boot-starter-swagger
			1.5.0.RELEASE
		
		
		
            mysql
            mysql-connector-java
        
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


3、yml文件

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        platform: mysql
        #url: jdbc:mysql://192.168.1.183:20001/dna?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSl=false
        url: jdbc:mysql://127.0.0.1:3306/ly?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSl=false
        username: root
        password: 123456
        initialSize: 10
        minIdle: 10
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        filters: stat,wall,log4j2
        logSlowSql: true
    jpa:
      hibernate:
        ddl-auto: update
        naming:
          physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #按字段名字建表
        show-sql: true
        database: mysql
        database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    http:
        encoding:
                charset: utf-8
                enabled: true
                force: true
    cache:
      type: ehcache
      ehcache:
        config: classpath:ehcache.xml
    redis:
     host: 127.0.0.1
     port: 6379
     timeout: 20000
#    集群环境打开下面注释,单机不需要打开
#    cluster:
#      集群信息
#      nodes: xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx
#      #默认值是5 一般当此值设置过大时,容易报:Too many Cluster redirections
#      maxRedirects: 3
    pool:
      max-active: 8
      min-idle: 0
      max-idle: 8
      max-wait: -1
      password:
      jpa:
      #按字段名字建表

#mybatis是独立节点,需要单独配置
mybatis:
  typeAliasesPackage: com.example.ehcache.*
  mapperLocations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true

server:
  port: 1234
  session-timeout: 30
  tomcat.max-threads: 0
  tomcat.uri-encoding: UTF-8
  servlet:
     context-path: /test

logging:
  config: classpath:log4j2-spring.xml
  #redis集群
  #热部署生效
  #设置重启的目录
  devtools:
    restart:
      enabled:true
      additional-paths:src/main/java

4、配置自定义角色类

package com.example.demo.shiro.role;

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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.example.demo.shiro.entity.SysPermission;
import com.example.demo.shiro.entity.SysRole;
import com.example.demo.shiro.entity.Users;
import com.example.demo.shiro.service.UsersService;

import lombok.extern.log4j.Log4j2;
/**
 * 
 *  @desc shiro核心配置类
 *	@author luobw
 * 
 *  2019年4月29日
 */
@Log4j2
public class MyShiroRealm extends AuthorizingRealm{

	@Autowired
	UsersService usersService;
	
	//权限信息,包括角色以及权限
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		log.info("-----权限信息------->");
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		Users user = (Users) principals.getPrimaryPrincipal();
		for (SysRole role : user.getRoleList()) {//获取角色
			authorizationInfo.addRole(role.getRole());
			for (SysPermission permission : role.getPermissions()) {//获取权限
				authorizationInfo.addStringPermission(permission.getPermission());
			}
		}
		return authorizationInfo;
	}
	/*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		log.info("-----身份验证------->");
		String userName = (String) token.getPrincipal();
		log.info("---------->"+token.getCredentials());
		Users users = usersService.findByUserName(userName);
		log.info("-------->"+users);
		
		if(users == null) {
			return null;
		}
		//实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo
				(users, //这里传入的是user对象,比对的是用户名,直接传入用户名也没错,但是在授权部分就需要自己重新从数据库里取权限
						users.getPassword(), 
						ByteSource.Util.bytes(users.getCredentialsSalt()),getName());
		return simpleAuthenticationInfo;
	}

}

5、配置shiro自定义加载类

package com.example.demo.shiro.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.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import com.example.demo.shiro.role.MyShiroRealm;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
/**
 * 
 *  @desc shiro配置
 *	@author luobw
 * 
 *  2019年4月29日
 */
@Configuration
public class ShiroConfig {
   @Bean
   public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
      System.out.println("ShiroConfiguration.shirFilter()");
      ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
      shiroFilterFactoryBean.setSecurityManager(securityManager);
      //拦截器.
      Map filterChainDefinitionMap = new LinkedHashMap();
      // 配置不会被拦截的链接 顺序判断,因为前端模板采用了thymeleaf,这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
      filterChainDefinitionMap.put("/css/**", "anon");
      filterChainDefinitionMap.put("/fonts/**", "anon");
      filterChainDefinitionMap.put("/img/**", "anon");
      filterChainDefinitionMap.put("/js/**", "anon");
      filterChainDefinitionMap.put("/html/**", "anon");
      //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
      filterChainDefinitionMap.put("/logout", "logout");
      filterChainDefinitionMap.put("/login", "anon");
      //:这是一个坑呢,一不小心代码就不好使了;
      //
      filterChainDefinitionMap.put("/**", "authc");
      // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
      //传统项目中,登出后应重定向请求,到登录界面或其他指定界面,在前后端分离的项目中,我们应该返回json信息。在上面提到的ShiroConfig中配置了默认登录路由
      shiroFilterFactoryBean.setLoginUrl("/unauth");
      // 登录成功后要跳转的链接
      shiroFilterFactoryBean.setSuccessUrl("/index");

      //未授权界面;
      shiroFilterFactoryBean.setUnauthorizedUrl("/403");
      shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
      return shiroFilterFactoryBean;
   }

   /**
    * 凭证匹配器
    * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
    * )
    * @return
    */
   @Bean
   public HashedCredentialsMatcher hashedCredentialsMatcher(){
      HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
      hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
      hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
      return hashedCredentialsMatcher;
   }

   @Bean
   public MyShiroRealm myShiroRealm(){
      MyShiroRealm myShiroRealm = new MyShiroRealm();
      myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
      return myShiroRealm;
   }


   @Bean
   public SecurityManager securityManager(){
      DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
      securityManager.setRealm(myShiroRealm());
      return securityManager;
   }

   /**
    *  开启shiro aop注解支持.
    *  使用代理方式;所以需要开启代码支持;
    * @param securityManager
    * @return
    */
   @Bean
   public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
      AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
      authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
      return authorizationAttributeSourceAdvisor;
   }

   @Bean(name="simpleMappingExceptionResolver")
   public SimpleMappingExceptionResolver
   createSimpleMappingExceptionResolver() {
      SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
      Properties mappings = new Properties();
      mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
      mappings.setProperty("UnauthorizedException","/user/403");
      r.setExceptionMappings(mappings);  // None by default
      r.setDefaultErrorView("error");    // No default
      r.setExceptionAttribute("exception");     // Default is "exception"
      //r.setWarnLogCategory("example.MvcLogger");     // No default
      return r;
   }
}

6、涉及到的用户表、角色表、权限表

用户实体类

package com.example.demo.shiro.entity;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.format.annotation.DateTimeFormat;


@Entity
@Table(name = "users")
public class Users {
    @Id
    @GenericGenerator(name="generator",strategy = "native")
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Integer userId;
    @Column(nullable = false, unique = true)
    private String userName; //登录用户名
    @Column(nullable = false)
    private String name;//名称(昵称或者真实姓名,根据实际情况定义)
    @Column(nullable = false)
    private String password;
    private String salt;//加密密码的盐
    private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.
    @ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
    @JoinTable(name = "SysUserRole", 
    joinColumns = {
    		@JoinColumn(name = "userId")}, 
    inverseJoinColumns ={
    		@JoinColumn(name = "roleId")})
    private List roleList;// 一个用户具有多个角色
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    private LocalDateTime createTime;//创建时间
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate expiredDate;//过期日期
    private String email;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public LocalDate getExpiredDate() {
        return expiredDate;
    }

    public void setExpiredDate(LocalDate expiredDate) {
        this.expiredDate = expiredDate;
    }
   
    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

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

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public byte getState() {
        return state;
    }

    public void setState(byte state) {
        this.state = state;
    }

    public List getRoleList() {
        return roleList;
    }

    public void setRoleList(List roleList) {
        this.roleList = roleList;
    }

    /**
     * 密码盐. 重新对盐重新进行了定义,用户名+salt,这样就不容易被破解,可以采用多种方式定义加盐
     * @return
     */
    public String getCredentialsSalt(){
        return this.userName+this.salt;
    }

}

角色实体类

package com.example.demo.shiro.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "sysrole")
public class SysRole {
    @Id
    @GenericGenerator(name="generator",strategy = "native")
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Integer roleId; // 编号
    @Column(nullable = false, unique = true)
    private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的:
    private String description; // 角色描述,UI界面显示使用
    private Boolean available = Boolean.TRUE; // 是否可用,如果不可用将不会添加给用户

    //角色 -- 权限关系:多对多关系;
    @ManyToMany(fetch= FetchType.EAGER)
    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})
    private List permissions;

    // 用户 - 角色关系定义;
    @ManyToMany
    @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="userId")})
    private List users;// 一个角色对应多个用户

    public Integer getRoleId() {
        return roleId;
    }

    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }

    public String getRole() {
        return role;
    }

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

    public String getDescription() {
        return description;
    }

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

    public Boolean getAvailable() {
        return available;
    }

    public void setAvailable(Boolean available) {
        this.available = available;
    }

    public List getPermissions() {
        return permissions;
    }

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

    public List getUsers() {
        return users;
    }

    public void setUsers(List users) {
        this.users = users;
    }
}

权限实体类

package com.example.demo.shiro.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "syspermission")
public class SysPermission {
    @Id
    @GenericGenerator(name="generator",strategy = "native")
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Integer permissionId;//主键.
    @Column(nullable = false)
    private String permissionName;//名称.
    @Column(columnDefinition="enum('menu','button')")
    private String resourceType;//资源类型,[menu|button]
    private String url;//资源路径.
    private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
    private Long parentId; //父编号
    private String parentIds; //父编号列表
    private Boolean available = Boolean.TRUE;
    //角色 -- 权限关系:多对多关系;
    @ManyToMany
    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})
    private List roles;

    public Integer getPermissionId() {
        return permissionId;
    }

    public void setPermissionId(Integer permissionId) {
        this.permissionId = permissionId;
    }

    public String getPermissionName() {
        return permissionName;
    }

    public void setPermissionName(String permissionName) {
        this.permissionName = permissionName;
    }

    public String getResourceType() {
        return resourceType;
    }

    public void setResourceType(String resourceType) {
        this.resourceType = resourceType;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getPermission() {
        return permission;
    }

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

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getParentIds() {
        return parentIds;
    }

    public void setParentIds(String parentIds) {
        this.parentIds = parentIds;
    }

    public Boolean getAvailable() {
        return available;
    }

    public void setAvailable(Boolean available) {
        this.available = available;
    }

    public List getRoles() {
        return roles;
    }

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

7、用户业务类,登录业务类

登录业务类

package com.example.demo.shiro.service;

import com.example.demo.shiro.entity.LoginResult;

public interface LoginService {
	LoginResult login(String userName,String password);
    void logout();

}

用户业务类

package com.example.demo.shiro.service;

import com.example.demo.shiro.entity.Users;

/**
 * 
 *  @desc
 *	@author luobw
 * 
 *  2019年4月29日
 */
public interface UsersService {
	Users findByUserName(String userName);
}

登录实现类

package com.example.demo.shiro.service.impl;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import com.example.demo.shiro.entity.LoginResult;
import com.example.demo.shiro.service.LoginService;
/**
 * 
 *  @desc  登录业务处理
 *	@author luobw
 * 
 *  2019年4月29日
 */
@Service
public class LoginServiceImpl implements LoginService {

	/**
	 * 登录
	 */
	@Override
	public LoginResult login(String userName, String password) {
		LoginResult loginResult = new LoginResult();
		if(userName==null || userName.isEmpty()) {
			loginResult.setLogin(false);
			loginResult.setResult("用户名不能为空");
			return loginResult;
		}
		String msg = "";
		//获取subject实例对象
		Subject subject = SecurityUtils.getSubject();
		//将用户名和密码封装到UsernamePasswordToken
		UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
		//认证
		try {
			subject.login(token);
			Session session = subject.getSession();
			session.setAttribute("userName", userName);
			loginResult.setLogin(true);
			return loginResult;
		} catch (UnknownAccountException e) {
			e.printStackTrace();
			 msg = "UnknownAccountException -- > 账号不存在:";
		} catch (IncorrectCredentialsException  e) {
			e.printStackTrace();
			 msg = "IncorrectCredentialsException -- > 密码不正确:";
		}catch (AuthenticationException e) {
            e.printStackTrace();
            msg="用户验证失败";
        }
		loginResult.setLogin(true);
		loginResult.setResult(msg);
		return loginResult;
	}
	/**
	 * 退出
	 */
	@Override
	public void logout() {
		Subject subject = SecurityUtils.getSubject();
		subject.logout();

	}

}

用户实现类

package com.example.demo.shiro.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.shiro.entity.Users;
import com.example.demo.shiro.repository.UserRepository;
import com.example.demo.shiro.service.UsersService;

@Service
public class ServiceImpl implements UsersService {

	@Autowired
	UserRepository userRepository;
	
	@Override
	public Users findByUserName(String userName) {
		return userRepository.findByUserName(userName);
	}

}

登录控制器类

package com.example.demo.shiro.controller;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.shiro.entity.LoginResult;
import com.example.demo.shiro.service.LoginService;

@RestController
public class MyLoginController {
	@Resource
	private LoginService loginService;
	LoginResult loginResult = new LoginResult();

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

	@RequestMapping("/403")
	public LoginResult unauthorizedRole() {
		System.out.println("------没有权限-------");
		loginResult.setResult("没有权限");
		return loginResult;
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public LoginResult login(Map map, HttpServletRequest request) throws Exception {
		System.out.println("login()");
		String userName = request.getParameter("userName");
		String password = request.getParameter("password");

		LoginResult loginResult = loginService.login(userName, password);
		if (loginResult.isLogin()) {
			return loginResult;
		} else {
			map.put("msg", loginResult.getResult());
			map.put("userName", userName);
			loginResult.setMap(map);
			return loginResult;
		}
	}

	@RequestMapping("/logout")
	public LoginResult logOut(HttpSession session) {
		loginService.logout();
		loginResult.setResult("退出成功");
		return loginResult;
	}

	   /**
			 * 未登录,shiro应重定向到登录界面,此处返回未登录状态信息由前端控制跳转页面
			 * 
			 * @return
			 */
				@RequestMapping(value = "/unauth")
				public LoginResult unauth() {
				 Map map = new HashMap();
				 map.put("code", "1000000");
				 map.put("msg", "未登录");
				 loginResult.setMap(map);
				 return loginResult;
				}
				@RequestMapping(value = "/auth")
				public LoginResult auth() {
				 Map map = new HashMap();
				 map.put("code", "200");
				 map.put("msg", "登录");
				 loginResult.setMap(map);
				 return loginResult;
				}
				@RequestMapping(value = "/user/403")
				public LoginResult exce() {
				 Map map = new HashMap();
				 map.put("code", "500");
				 map.put("msg", "数据异常");
				 loginResult.setMap(map);
				 return loginResult;
				}
	/*
	@RequestMapping(value = "/error")
	public LoginResult error() {
	 Map map = new HashMap();
	 map.put("code", "500");
	 map.put("msg", "error异常");
	 loginResult.setMap(map);
	 return loginResult;
	}*/

}

用户控制器类

package com.example.demo.shiro.controller;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.shiro.entity.LoginResult;

@RestController
@RequestMapping("/user")
public class UserController {
	 LoginResult loginResult = new LoginResult();
	/**
     * 用户查询.
     * @return
     */
    @RequestMapping(value = "/userList",method=RequestMethod.GET)
    @RequiresPermissions("user:view")//权限管理;
    public LoginResult userInfo(){
    	loginResult.setLogin(true);
    	loginResult.setResult("用户查询");
        return loginResult;
    }

    /**
     * 用户添加;
     * @return
     */
    @RequestMapping("/userAdd")
    @RequiresPermissions("user:add")//权限管理;
    public LoginResult userInfoAdd(){
    	loginResult.setLogin(true);
    	loginResult.setResult("用户添加");
        return loginResult;
    }

    /**
     * 用户删除;
     * @return
     */
    @RequestMapping("/userDel")
    @RequiresPermissions("user:del")//权限管理;
    public LoginResult userDel(){
    	loginResult.setLogin(true);
    	loginResult.setResult("用户删除");
        return loginResult;
    }
}

返回值类

package com.example.demo.shiro.entity;

import java.util.Map;

public class LoginResult {
    private boolean isLogin = false;
    private String result;

    private Map map;
    
    
    public Map getMap() {
		return map;
	}

	public void setMap(Map map) {
		this.map = map;
	}

	public boolean isLogin() {
        return isLogin;
    }

    public void setLogin(boolean login) {
        isLogin = login;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

启动项目自动创建表结构,需导入sql数据

INSERT INTO `users` (`userId`,`username`,`name`,`password`,`salt`,`state`)
VALUES ('1', 'admin', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', 0);

INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (1,0,'用户管理',0,'0/','user:view','menu','user/userList');
INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (2,0,'用户添加',1,'0/1','user:add','button','user/userAdd');
INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (3,0,'用户删除',1,'0/1','user:del','button','user/userDel');

INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (1,0,'管理员','admin');
INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (2,0,'VIP会员','vip');
INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (3,1,'test','test');

INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (1,1);
INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (2,1);
INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (3,2);

INSERT INTO `sysuserrole` (`roleid`,`userId`) VALUES (1,1);

7、运行调试

   1.未登录访问用户列表

get  192.168.1.63:1234/test/user/userList

Springboot整合shiro做安全框架(一)_第2张图片

2、登录请求

 post   192.168.1.63:1234/test/login?userName=admin&password=123456 

Springboot整合shiro做安全框架(一)_第3张图片

3、再次访问用户列表

 Springboot整合shiro做安全框架(一)_第4张图片

4、退出请求

get  192.168.1.63:1234/test/logout

Springboot整合shiro做安全框架(一)_第5张图片 

你可能感兴趣的:(SpringBoot)