您好!欢迎来到北极熊

北极熊

热门搜索: 任正非传    神雕侠侣    红楼梦   

Shiro之基本使用

分类:技术交流 时间:2022-09-26 22:00 浏览:142
概述
gitee地址:shiro初体验https://gitee.com/qiangning/shiro-learning.git1.什么是ShiroApache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。Shiro为解决下列问题(我喜欢称它们为应用安全的四要素)提供了保护应用的API:认证 - 用户身份识别,常被称为用户“登录”
内容

gitee地址:shiro初体验https://gitee.com/qiangning/shiro-learning.git

1.什么是Shiro

Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。

Shiro为解决下列问题(我喜欢称它们为应用安全的四要素)提供了保护应用的API:
认证 - 用户身份识别,常被称为用户“登录”;
授权 - 访问控制;
密码加密 - 保护或隐藏数据防止被偷窥;
会话管理 - 每用户相关的时间敏感的状态。
Shiro还支持一些辅助特性,如Web应用安全、单元测试和多线程,它们的存在强化了上面提到的四个要素

2.Shiro核心组件



2.1 Subject(主体):外部应用的交互,记录当前操作用户,Subject是通过SecurityManager安全管理器进行授权的;

2.2 SecurityManager(核心安全管理器):对全部Subject进行安全管理,他是核心,SecurityManager通过Authenticato进行认证,通过Authorize授权,通过SessionManager进行会话管理;

 Java

      SecurityManager是一个接口继承了Authenticato,Authorize,SessionManage这三个接口

2.3 Authenticator(认证器):对用户认证,它是一个接口,shiro提供了ModularRealmAuthenticator实现类,通过实现类可以满足基本要求,也可以自定义认证器;

2.4 Authorizer(授权器):用户通过认证器来判断用户是否有此功能操作权限;

2.5 Realm(领域) :相当于数据源,SecuityManager进行认证通过Realm来获取用户权限数据;(从数据库取数据)

2.6 SessionManager(会话管理) :shiro自定义了一套会话管理,他不依赖web的session,此特性可以使它实现单点登录;

2.7 SessionDAO(会话DAO) :是对session会话的操作,比如将session存储到数据库中,可通过jdbc存储到数据库;

2.8 CacheManager(缓存管理) :用户权限数据存储在缓存,提高性能;

2.9 Cryptography(密码管理) shiro提供的一套密码加密解密组件,方便开发;

3.认证

3.1 Subject : 主体 ::进行认证的都叫主体

3.2 Principal :身份信息::必须要有唯一性,一个主体能有多个身份,但是必须有一个主身份

3.3 Credential :凭证信息::只有主体知道的安全信息

 Java

<dependency> 
  <groupId>org.apache.shiro</groupId> 
  <artifactId>shiro-core</artifactId> 
  <version>1.5.3</version> </dependency> 
 
 
 配置文件为 .ini后缀;单击测试shiro不用操作数据库;

demo简单例子

认证代码:

 Java

public class HaoAuthenticator { 
  public static void main(String[] args) { 
      //1.创建安全管理器对象 
      DefaultSecurityManager securityManager = new DefaultSecurityManager(); 
      //2.安全管理器设置realm 
      securityManager.setRealm(new IniRealm("classpath:shiro.ini")); 
      //3.SecurityUtils 全局安全工具类设置安全管理器 
      SecurityUtils.setSecurityManager(securityManager); 
      //4.关键对象 subject 主体 
      Subject subject = SecurityUtils.getSubject(); 
 
      //5.创建令牌 
      UsernamePasswordToken token = new UsernamePasswordToken("admin","root"); 
 
      try{ 
          System.out.println("认证状态: "+ subject.isAuthenticated()); 
          subject.login(token);//用户认证 
          System.out.println("认证状态: "+ subject.isAuthenticated()); 
      }catch (UnknownAccountException e){ 
          e.printStackTrace(); 
          System.out.println("认证失败: 用户名不存在~"); 
      }catch (IncorrectCredentialsException e){ 
          e.printStackTrace(); 
          System.out.println("认证失败: 密码错误~"); 
      } 
  } }

4.Realm自定义

SimpleAccountRealm主要认证和授权源码:

 Java

public class SimpleAccountRealm extends AuthorizingRealm { //认证 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        UsernamePasswordToken upToken = (UsernamePasswordToken) token; 
        SimpleAccount account = getUser(upToken.getUsername()); 
 
        if (account != null) { 
 
            if (account.isLocked()) { 
                throw new LockedAccountException("Account [" + account + "] is locked."); 
            } 
            if (account.isCredentialsExpired()) { 
                String msg = "The credentials for account [" + account + "] are expired"; 
                throw new ExpiredCredentialsException(msg); 
            } 
 
        } 
 
        return account; 
    } 
    //授权 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
        String username = getUsername(principals); 
        USERS_LOCK.readLock().lock(); 
        try { 
            return this.users.get(username); 
        } finally { 
            USERS_LOCK.readLock().unlock(); 
        } 
    } }

自定义Realm:继承 AuthorizingRealm重写认证和授权

 Java

public class CustomerRealm extends AuthorizingRealm { 
    //授权 
    @Override 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
        System.out.println("===授权方法======="); 
        return null; 
    } 
 
    //认证 
    @Override 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        //在token中获取用户名 
        String principal = (String) token.getPrincipal(); 
         
        System.out.println(principal); 
        //根据身份信息使用jdbc mybatis查询数据库 
        if("admin".equals(principal)){ 
         //参数1:返回数据库中正确的用户名   //参数2:返回数据库中正确密码  //参数3:提供当前realm的名字 this.getName(); 
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,"root",this.getName()); 
            return simpleAuthenticationInfo; 
        } 
        return null; 
    } }

测试自定义Realm

 Java

public class HaoCustomerRealmAuthenticator { 
    public static void main(String[] args) { 
 
        //创建securityManager 
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); 
        //设置自定义realm 
        defaultSecurityManager.setRealm(new CustomerRealm()); 
        //将安全工具类设置安全工具类 
        SecurityUtils.setSecurityManager(defaultSecurityManager); 
        //通过安全工具类获取subject 
        Subject subject = SecurityUtils.getSubject(); 
        //创建token 
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "root"); 
        try { 
            subject.login(token); 
            System.out.println(subject.isAuthenticated()); 
        } catch (UnknownAccountException e) { 
            e.printStackTrace(); 
            System.out.println("用户名错误"); 
        } catch (IncorrectCredentialsException e) { 
            e.printStackTrace(); 
            System.out.println("密码错误"); 
        } 
       //认证用户进行授权 
        if(subject.isAuthenticated()){ 
            //1.基于角色权限控制 
            System.out.println(subject.hasRole("root")); 
       } 
    } }

使用加密来验证:md5+Salt(”盐“)代码:

 Java

public class HaoShiroMD5 { 
    public static void main(String[] args) { 
 
        //使用MD5加密 
        Md5Hash md5Hash = new Md5Hash("admin"); 
        System.out.println(md5Hash.toHex()); 
         
        //使用MD5 + Salt处理 
        Md5Hash md5Hash1 = new Md5Hash("admin", "X0*7ps"); 
        System.out.println(md5Hash1.toHex()); 
         
        //使用MD5 + Salt + Hash散列 
        Md5Hash md5Hash2 = new Md5Hash("admin", "X0*7ps", 1024); 
        System.out.println(md5Hash2.toHex()); 
    } }

使用自定义Realm+MD5+Salt代码

 Java

public class CustomerMd5Realm extends AuthorizingRealm { 
 
    //授权 
    @Override 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
        String primaryPrincipal = (String) principals.getPrimaryPrincipal(); 
        System.out.println("身份信息: "+primaryPrincipal); 
 
        //根据身份信息 用户名 获取当前用户的角色信息 
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 
 
        return simpleAuthorizationInfo; 
    } 
 
    @Override 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        //获取身份信息 
        String principal = (String) token.getPrincipal(); 
 
        //根据用户名查询数据库 
        if ("admin".equals(principal)) { 
            //参数1: 数据库用户名  参数2:数据库md5+salt之后的密码  参数3:注册时的随机盐  参数4:realm的名字 
            return new SimpleAuthenticationInfo(principal, 
                    "e4f9bf3e0c58f045e62c23c533fcf633", 
                    ByteSource.Util.bytes("X0*7ps"), 
                    this.getName()); 
        } 
        return null; 
    } }

测试:

 Java

public class HaoCustomerMd5RealmAuthenicator { 
 
    public static void main(String[] args) { 
 
        //创建安全管理器 
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); 
        //注入realm 
        CustomerMd5Realm realm = new CustomerMd5Realm(); 
        //设置realm使用hash凭证匹配器 
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); 
        //使用算法 
        credentialsMatcher.setHashAlgorithmName("md5"); 
        //散列次数 
        credentialsMatcher.setHashIterations(1024); 
        realm.setCredentialsMatcher(credentialsMatcher); 
        defaultSecurityManager.setRealm(realm); 
        //将安全管理器注入安全工具 
        SecurityUtils.setSecurityManager(defaultSecurityManager); 
        //通过安全工具类获取subject 
        Subject subject = SecurityUtils.getSubject(); 
        //认证 
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "root"); 
 
        try { 
            subject.login(token); 
            System.out.println("登录成功"); 
        } catch (UnknownAccountException e) { 
            e.printStackTrace(); 
            System.out.println("用户名错误"); 
        }catch (IncorrectCredentialsException e){ 
            e.printStackTrace(); 
            System.out.println("密码错误"); 
        } 
        } }

4.授权

访问控制,就是能访问那些东西网页资源,
授权可简 单理解为who对what(which)进行How操作:

4.1 WHO

Who,即主体(Subject),主体需要访问系统中的资源。

4.2 WHAT

What,即资源(Resource),如系统菜单、页面、按钮、类方法、
系统商品信息等。资源包括_资源类型和资源实例_,比如商品信息

4.3 HOW

How,权限/许可(Permission),规定了主体对资源的操作许可,

授权方式
基于角色访问

 Java

if(subject.hasRore('admin')){ //操作什么资源 }

基于资源访问

 Java

if(subject.isPermission("user:update:01")){ //资源实例 //对01用户进行修改 } if(subject.isPermission("user:update:*")){  //资源类型 //对01用户进行修改 }

权限字符串: *资源标识符:操作:资源实例标识符;
eg:
用户创建权钱:user:create,或user:create:

用户修改实例:user:update:001
用户实例所有权限:user:*:001

shiro授权实现方式:
编程式:

 Java

Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) { 
	//有权限 } else { 
	//无权限 }

注解式:

 Java

@RequiresRoles("admin") public void hello() { 
	//有权限 }

标签式:

 Java

JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成: 
<shiro:hasRole name="admin"> <!— 有权限—> </shiro:hasRole> 注意: Thymeleaf 中使用shiro需要额外集成!

开发授权:
先认证再授权;

 Java

package com.baizhi.realm; 
 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; 
 /** 
 * 使用自定义realm 加入md5 + salt +hash 
 */ public class CustomerMd5Realm extends AuthorizingRealm { 
 
    //授权 
    @Override 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
        String primaryPrincipal = (String) principals.getPrimaryPrincipal(); 
        System.out.println("身份信息: "+primaryPrincipal); 
 
        //根据身份信息 用户名 获取当前用户的角色信息,以及权限信息  xiaochen  admin user 
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 
 
        //将数据库中查询角色信息赋值给权限对象 
        simpleAuthorizationInfo.addRole("admin"); 
        simpleAuthorizationInfo.addRole("user"); 
 
        //将数据库中查询权限信息赋值个权限对象 
        simpleAuthorizationInfo.addStringPermission("user:*:01"); 
        simpleAuthorizationInfo.addStringPermission("product:create"); 
 
 
        return simpleAuthorizationInfo; 
    } 
 
    @Override 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        //获取身份信息 
        String principal = (String) token.getPrincipal(); 
 
        //根据用户名查询数据库 
        if ("Hao".equals(principal)) { 
            //参数1: 数据库用户名  参数2:数据库md5+salt之后的密码  参数3:注册时的随机盐  参数4:realm的名字 
            return new SimpleAuthenticationInfo(principal, 
                    "e4f9bf3e0c58f045e62c23c533fcf633", 
                    ByteSource.Util.bytes("X0*7ps"), 
                    this.getName()); 
        } 
        return null; 
    } }

测试

 Java

public class HaoCustomerMd5RealmAuthenicator { 
 
    public static void main(String[] args) { 
 
        //创建安全管理器 
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); 
        //注入realm 
        CustomerMd5Realm realm = new CustomerMd5Realm(); 
        //设置realm使用hash凭证匹配器 
 
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); 
        //使用算法 
        credentialsMatcher.setHashAlgorithmName("md5"); 
        //散列次数 
        credentialsMatcher.setHashIterations(1024); 
        realm.setCredentialsMatcher(credentialsMatcher); 
 
        defaultSecurityManager.setRealm(realm); 
        //将安全管理器注入安全工具 
        SecurityUtils.setSecurityManager(defaultSecurityManager); 
 
        //通过安全工具类获取subject 
        Subject subject = SecurityUtils.getSubject(); 
 
        //认证 
        UsernamePasswordToken token = new UsernamePasswordToken("hao", "1111"); 
 
        try { 
            subject.login(token); 
            System.out.println("登录成功"); 
        } catch (UnknownAccountException e) { 
            e.printStackTrace(); 
            System.out.println("用户名错误"); 
        }catch (IncorrectCredentialsException e){ 
            e.printStackTrace(); 
            System.out.println("密码错误"); 
        } 
 
 
        //授权 
        if(subject.isAuthenticated()){ 
 
            //基于角色权限控制 
            System.out.println(subject.hasRole("super")); 
 
            //基于多角色权限控制 
            System.out.println(subject.hasAllRoles(Arrays.asList("admin", "super"))); 
 
            //是否具有其中一个角色 
            boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "super", "user")); 
            for (boolean aBoolean : booleans) { 
                System.out.println(aBoolean); 
            } 
            System.out.println("=============================================="); 
 
            //基于权限字符串的访问控制  资源标识符:操作:资源类型 
            System.out.println("权限:"+subject.isPermitted("user:update:01")); 
            System.out.println("权限:"+subject.isPermitted("product:create:02")); 
 
            //分别具有那些权限 
            boolean[] permitted = subject.isPermitted("user:*:01", "order:*:10"); 
            for (boolean b : permitted) { 
                System.out.println(b); 
            } 
 
            //同时具有哪些权限 
            boolean permittedAll = subject.isPermittedAll("user:*:01", "product:create:01"); 
            System.out.println(permittedAll); 
        } 
 
    } }

5.整合springboot

5.1引入依赖

 Java

<dependency> 
  <groupId>org.apache.shiro</groupId> 
  <artifactId>shiro-spring-boot-starter</artifactId> 
  <version>1.5.3</version> </dependency>

5.1.1创建配置类

常见过滤器

配置缩写

对应的过滤器

功能

anon

AnonymousFilter

指定url可以匿名访问

authc

FormAuthenticationFilter

指定url需要form表单登录,默认会从请求中获取username、password,rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。

authcBasic

BasicHttpAuthenticationFilter

指定url需要basic登录

logout

LogoutFilter

登出过滤器,配置指定url就可以实现退出功能,非常方便

noSessionCreation

NoSessionCreationFilter

禁止创建会话

perms

PermissionsAuthorizationFilter

需要指定权限才能访问

port

PortFilter

需要指定端口才能访问

rest

HttpMethodPermissionFilter

将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释

roles

RolesAuthorizationFilter

需要指定角色才能访问

ssl

SslFilter

需要https请求才能访问

user

UserFilter

需要已登录或“记住我”的用户才能访问

==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

5.2 目录:

在这里插入图片描述

登录,注册,加盐,数据库,认证:

ShiroConfig

 Java

package com.hao.shiro.config; 
 import com.hao.shiro.shiro.realms.CustomerRealm; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.realm.Realm; 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 java.util.HashMap; import java.util.Map; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Configuration 
public class ShiroConfig { 
 
 
    //创建shiro的filter//负责拦截所有请求 
    @Bean 
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ 
 
 
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 
        //注入安全管理器 
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); 
        //配置系统授限资源 
 
        //配置系统公共资源 
        Map<String,String> map=new HashMap<>(); 
        map.put("/user/login.jsp","anon"); 
        map.put("/user/register.jsp","anon"); 
        map.put("/index.jsp","authc");//请求这个资源需要认证和授权 
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map); 
        //默认认证界面 
        shiroFilterFactoryBean.setLoginUrl("/login.jsp"); 
 
        return shiroFilterFactoryBean; 
    } 
 
    //创建安全管理器 
    @Bean 
    public DefaultWebSecurityManager getdefaultWebSecurityManager (Realm realm){ 
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); 
        //给安全管理器设置 
        defaultWebSecurityManager.setRealm(realm); 
        return defaultWebSecurityManager; 
    } 
 
    //创建自定义realm 
    @Bean 
    public Realm getRealm(){ 
 
        CustomerRealm customerRealm = new CustomerRealm(); 
        //设置hashed凭证匹配器 
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); 
        //设置md5加密 
        credentialsMatcher.setHashAlgorithmName("md5"); 
        //设置散列次数 
        credentialsMatcher.setHashIterations(1024); 
        customerRealm.setCredentialsMatcher(credentialsMatcher); 
        return customerRealm; 
 
 
    } 
 
 }

UserController

 Java

package com.hao.shiro.controller; 
 
 import com.hao.shiro.entity.User; import com.hao.shiro.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; 
 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Controller 
@RequestMapping("user") public class UserController { 
 
 
 
    @RequestMapping("/logout") 
    public String logout(){ 
        Subject subject = SecurityUtils.getSubject(); 
        subject.logout(); 
        System.out.println("退出登录"); 
        return "redirect:/login.jsp"; 
 
    } 
 
 
    @Autowired 
    private UserService userService; 
 
    /** 
     * 用户注册 
     */ 
    @RequestMapping("register") 
    public String register(User user) { 
        try { 
            userService.register(user); 
            return "redirect:/login.jsp"; 
        }catch (Exception e){ 
            e.printStackTrace(); 
            return "redirect:/register.jsp"; 
        } 
    } 
 
    @RequestMapping("login") 
    public String login(String username,String password){ 
 
        //获取主体对象 
        Subject subject= SecurityUtils.getSubject(); 
 
        try { 
            subject.login(new UsernamePasswordToken(username,password)); 
            return "redirect:/index.jsp"; 
        }catch (UnknownAccountException e){ 
            e.printStackTrace(); 
            System.out.println("用户名错误"); 
        }catch (IncorrectCredentialsException e){ 
            e.printStackTrace(); 
            System.out.println("密码错误"); 
        } 
        return "redirect:/login.jsp"; 
 
    } 
 }

UserDAO

 Java

package com.hao.shiro.dao; 
 import com.hao.shiro.entity.User; import org.apache.ibatis.annotations.Mapper; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Mapper 
public interface UserDAO { 
    void save(User user); 
    User findByUserName(String username); }

User

 Java

package com.hao.shiro.entity; 
 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Data 
@Accessors(chain = true) @AllArgsConstructor 
@NoArgsConstructor 
public class User { 
    private String id; 
    private String username; 
    private String password; 
    private String salt; }

UserService

 Java

package com.hao.shiro.service; 
 import com.hao.shiro.entity.User; 
 public interface UserService { 
    void register(User user); 
    User findByUserName(String username); }

UserServiceImpl

 Java

package com.hao.shiro.service; 
 import com.hao.shiro.dao.UserDAO; import com.hao.shiro.entity.User; import com.hao.shiro.utils.SaltUtils; import org.apache.shiro.crypto.hash.Md5Hash; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Service("userService") @Transactional 
public class UserServiceImpl implements UserService { 
    @Autowired 
    private UserDAO userDAO; 
 
 
    @Override 
    public User findByUserName(String username) { 
        return userDAO.findByUserName(username); 
    } 
 
    @Override 
    public void register(User user){ 
 
        //处理业务 
        //加密 
        //处理业务调用dao 
        //1.生成随机盐 
        String salt = SaltUtils.getSalt(8); 
        //2.将随机盐保存到数据 
        user.setSalt(salt); 
        //3.明文密码进行md5 + salt + hash散列 
        Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024); 
        user.setPassword(md5Hash.toHex()); 
        userDAO.save(user); 
 
 
 
    } }

CustomerRealm

 Java

package com.hao.shiro.shiro.realms; 
 import com.hao.shiro.entity.User; import com.hao.shiro.service.UserService; import com.hao.shiro.utils.ApplicationContextUtils; 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.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.util.ObjectUtils; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ public class CustomerRealm extends AuthorizingRealm { 
    //处理授权 
    @Override 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
        return null; 
    } 
    //处理认证 
    @Override 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        System.out.println("--------进入认证--------"); 
 
        //根据身份信息 
        String principal = (String) token.getPrincipal(); 
        //在工厂中获取service对象 
        UserService userService = (UserService) ApplicationContextUtils.getBean("userService"); 
        //根据身份信息查询 
        User user = userService.findByUserName(principal); 
 
        if(!ObjectUtils.isEmpty(user)){ 
            //返回数据库信息 
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), 
                    ByteSource.Util.bytes(user.getSalt()),this.getName()); 
        } 
 
        return null; 
    } }

ApplicationContextUtils

 Java

package com.hao.shiro.utils; 
 import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ @Component 
public class ApplicationContextUtils implements ApplicationContextAware { 
    private static ApplicationContext context; 
    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
        this.context=applicationContext; 
    } 
    public static Object getBean(String beanName){ 
 
        return context.getBean(beanName); 
    } 
 
 }

SaltUtils

 Java

package com.hao.shiro.utils; 
 import java.util.Random; 
 /* 
 *@hao 
 * 
 * 
 * 
 */ public class SaltUtils { 
    /** 
     * 生成salt的静态方法 
     * @param n 
     * @return 
     */ 
    public static String getSalt(int n){ 
        char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); 
        StringBuilder sb = new StringBuilder(); 
        for (int i = 0; i < n; i++) { 
            char aChar = chars[new Random().nextInt(chars.length)]; 
            sb.append(aChar); 
        } 
        return sb.toString(); 
    } }

applicattin

 Java

server.port=8080 
 server.servlet.context-path=/shiro 
spring.application.name=shiro 
 
spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp 
 
 
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 
spring.datasource.driver-class-name=com.mysql.jdbc.Driver 
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false spring.datasource.username=root 
spring.datasource.password=root 
 
 
 
mybatis.type-aliases-package=com.hao.shiro.entity 
mybatis.mapper-locations=classpath:mapper/*.xml

Mapper->UserDaoMapper.xml

 Java

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper 
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hao.shiro.dao.UserDAO"> 
 
    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id"> 
  insert into t_user values(#{id},#{username},#{password},#{salt}) 
 </insert> 
 
    <select id="findByUserName" parameterType="String" resultType="User"> 
  select id,username,password,salt from t_user 
  where username = #{username} </select> </mapper>

webapp–>
index.jsp

 Java

<%@page contentType="text/html;  utf-8"  pageEncoding="utf-8" isELIgnored="false" %> <html> <head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" 
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> 
    <title>主页</title> </head> <body> <h1>系统主页</h1> <a href="${pageContext.request.contextPath}/user/logout">退出登录</a> <ol> 
    <li><a href="">用户页面</a></li> 
    <li><a href="">食品页面</a></li> 
    <li><a href="">订单页面</a></li> 
    <li><a href="">物流页面</a></li> 
 </ol> 
 </body> </html>

login.jsp

 Java

<%@page contentType="text/html;  utf-8"  pageEncoding="utf-8" isELIgnored="false" %> <!<html> <head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" 
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> 
    <title>用户登录</title> </head> <body> <h1>用户登录</h1> 
 <form action="${pageContext.request.contextPath}/user/login" method="get"> 
    用户名:<input type="text" name="username"><br> 
    密  码:<input type="text" name="password"> 
  <input type="submit" value="登录"><a href="/shiro/register.jsp">立即注册</a> </form> 
 
 </body> </html>

register.jsp

 Java

<%@page contentType="text/html;  utf-8"  pageEncoding="utf-8" isELIgnored="false" %> <!<html> <head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" 
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> 
    <title>用户登录</title> </head> <body> <h1>用户注册</h1> 
 <form action="${pageContext.request.contextPath}/user/register" method="get"> 
    用户名:<input type="text" name="username"><br> 
    密  码:<input type="text" name="password"> 
    <input type="submit" value="立即注册"> </form> 
 
 </body> </html>

授权整合以及redis缓存整合

在这里插入图片描述

开启自带缓存

 Java

 //开启自带的缓存管理 
        customerRealm.setCacheManager(new EhCacheManager()); 
        customerRealm.setCachingEnabled(true);//开启全局缓存 
        customerRealm.setAuthenticationCachingEnabled(true);//认证认证缓存 
        customerRealm.setAuthenticationCacheName("authenticationCache"); 
        customerRealm.setAuthorizationCachingEnabled(true);//开启授权缓存 
        customerRealm.setAuthorizationCacheName("authorizationCache"); 
        return customerRealm;

pom主要导入依赖

 Java

        <dependency> 
            <groupId>org.apache.shiro</groupId> 
            <artifactId>shiro-spring-boot-starter</artifactId> 
            <version>1.5.3</version> 
        </dependency> 
 
 
        <dependency> 
            <groupId>org.apache.tomcat.embed</groupId> 
            <artifactId>tomcat-embed-jasper</artifactId> 
        </dependency> 
        <dependency> 
            <groupId>javax.servlet</groupId> 
            <artifactId>jstl</artifactId> 
            <version>1.2</version> 
        </dependency> 
 
        <!--mybatis相关依赖--> 
        <dependency> 
            <groupId>org.mybatis.spring.boot</groupId> 
            <artifactId>mybatis-spring-boot-starter</artifactId> 
            <version>2.1.2</version> 
        </dependency> 
 
        <!--mysql--> 
        <dependency> 
            <groupId>mysql</groupId> 
            <artifactId>mysql-connector-java</artifactId> 
            <version>5.1.38</version> 
        </dependency> 
 
 
        <!--druid--> 
        <dependency> 
            <groupId>com.alibaba</groupId> 
            <artifactId>druid</artifactId> 
            <version>1.1.19</version> 
        </dependency> 
        <!--引入shiro和ehcache--> 
        <dependency> 
            <groupId>org.apache.shiro</groupId> 
            <artifactId>shiro-ehcache</artifactId> 
            <version>1.5.3</version> 
        </dependency> 
 
        <!--redis整合springboot--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-data-redis</artifactId> 
        </dependency>

配置文件

 Java

server.port=8080 
 server.servlet.context-path=/shiro 
spring.application.name=shiro 
 
spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp 
 
 
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 
spring.datasource.driver-class-name=com.mysql.jdbc.Driver 
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false spring.datasource.username=root 
spring.datasource.password=root 
 
 
 
mybatis.type-aliases-package=com.hao.shiro.entity 
mybatis.mapper-locations=classpath:mapper/*.xml 
 
spring.redis.port=6379 spring.redis.host=localhost 
spring.redis.database=0

sql

 Java

/* 
SQLyog Professional v12.09 (64 bit) 
MySQL - 5.7.34-log : Database - shiro 
********************************************************************* 
*/ 
 
 /*!40101 SET NAMES utf8 */; 
 /*!40101 SET SQL_MODE=''*/; 
 /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`shiro` /*!40100 DEFAULT CHARACTER SET utf8 */; 
 USE `shiro`; 
 /*Table structure for table `t_perms` */ 
 DROP TABLE IF EXISTS `t_perms`; 
 CREATE TABLE `t_perms` ( 
  `id` int(6) NOT NULL AUTO_INCREMENT, 
  `name` varchar(80) DEFAULT NULL, 
  `url` varchar(255) DEFAULT NULL, 
  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 
 /*Data for the table `t_perms` */ 
 insert  into `t_perms`(`id`,`name`,`url`) values (1,'user:*:*',NULL),(2,'product:*:01',NULL),(3,'order:*:*',NULL); 
 /*Table structure for table `t_role` */ 
 DROP TABLE IF EXISTS `t_role`; 
 CREATE TABLE `t_role` ( 
  `id` int(6) NOT NULL AUTO_INCREMENT, 
  `name` varchar(60) DEFAULT NULL, 
  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 
 /*Data for the table `t_role` */ 
 insert  into `t_role`(`id`,`name`) values (1,'admin'),(2,'user'),(3,'product'); 
 /*Table structure for table `t_role_perms` */ 
 DROP TABLE IF EXISTS `t_role_perms`; 
 CREATE TABLE `t_role_perms` ( 
  `id` int(6) NOT NULL, 
  `roleid` int(6) DEFAULT NULL, 
  `permsid` int(6) DEFAULT NULL, 
  PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 /*Data for the table `t_role_perms` */ 
 insert  into `t_role_perms`(`id`,`roleid`,`permsid`) values (1,1,1),(2,1,2),(3,2,1),(4,3,2),(5,1,3); 
 /*Table structure for table `t_user` */ 
 DROP TABLE IF EXISTS `t_user`; 
 CREATE TABLE `t_user` ( 
  `id` int(6) NOT NULL AUTO_INCREMENT, 
  `username` varchar(40) DEFAULT NULL, 
  `password` varchar(40) DEFAULT NULL, 
  `salt` varchar(255) DEFAULT NULL, 
  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; 
 /*Data for the table `t_user` */ 
 insert  into `t_user`(`id`,`username`,`password`,`salt`) values (1,'hao','567f86681241739ba8cf3d26e52eaafc','XK&7UIS^'),(2,'qiang','d750daee137e0666193a1720732fe97d','UVcob7pR'); 
 /*Table structure for table `t_user_role` */ 
 DROP TABLE IF EXISTS `t_user_role`; 
 CREATE TABLE `t_user_role` ( 
  `id` int(6) NOT NULL, 
  `userid` int(6) DEFAULT NULL, 
  `roleid` int(6) DEFAULT NULL, 
  PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 /*Data for the table `t_user_role` */ 
 insert  into `t_user_role`(`id`,`userid`,`roleid`) values (1,1,1),(2,2,2),(3,2,3); 
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;


评论
资讯正文页右侧广告
联系我们
电话:18936411277
邮箱:1044412291@qq.com
时间:09:00 - 19:00
公众号:北格软件
底部广告