Shiro+Mybatis实现登录认证、授权功能
Shiro+Mybatis实现登录认证、授权功能
一、实现登录认证功能
1、流程:
- 跟据用户提交表单的账号,经Mybatis框架在数据库中查出User对象:
- 如果User为空,则会抛出异常:UnknownAccountException,没有此账户名。
- 如果不为空,则比对表单中的密码和User对象的密码是否相同(shiro框架自动完成,有加密),密码不相同则会抛出异常:IncorrectCredentialsException,密码错误;密码相同,则登陆成功。
- 跟据用户提交表单的账号,经Mybatis框架在数据库中查出User对象:
2、详细流程:
1)代码结构如图:

2)RouterController类接收表单的请求后,将用户提交的表单数据封装成令牌,并执行方法 subjec.login(token)(用令牌登陆),下面是RouterController的部分代码
@RequestMapping("/login")
public String login(String usr, String pwd, Model model){ //获取当前用户
Subject subject = SecurityUtils.getSubject(); //封装用户的登陆数据,生成令牌
UsernamePasswordToken token = new UsernamePasswordToken(usr,pwd); //用令牌登陆,如果没有异常则登陆成功
try{
subject.login(token);
//无异常则登陆成功
return "index";
}catch(UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch(IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
3)subjec.login(token)会调用UserRealm的认证方法doGetAuthenticationInfo(AuthenticationToken aToken)(UserRealm中有两个方法,一个授权,一个认证),下面是UserRealm的部分代码(认证方法):
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //先取令牌
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; //根据令牌信息从数据库中取出用户
User user = userService.getUserByEmail(token.getUsername());
if(user==null){
return null; //返回null,则抛出无用户名的异常
} //验证密码,Shiro自动验证,只需要把数据库的密码传过去就好了
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
二、实现授权功能
1、给请求设置权限,下面是ShiroConfig三病(Bean)的第一个病(Bean)ShiroFilterFactoryBean,主要负责给各种请求设置各种权限,只有拥有权限的用户才可访问请求
@Bean //此注解意思就是在程序开始运行前,会自动给spring托管
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//关联securityManager
bean.setSecurityManager(securityManager); //给请求设置权限
Map<String,String> filter = new LinkedHashMap<>();
filter.put("/user/information","perms[user:gr]"); //有权限"user:gr"才可访问
filter.put("/user/recommend","perms[user:tj]"); //有权限"user:tj"才可访问
filter.put("/","anon"); //anon 谁都可以访问 //把filter加载给bean
bean.setFilterChainDefinitionMap(filter); //当没有登陆时,跳转到此登陆界面
bean.setLoginUrl("/tologin"); //当没有权限时,跳转到此登陆界面
bean.setUnauthorizedUrl("/noautho"); return bean;
}
2、根据用户对象的perm(数据库中代表权限的字段)赋予当前用户权限,下面是UserRealm类中的授权方法:doGetAuthorizationInfo(PrincipalCollection principalCollection)
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //拿到当前登陆的这个对象,根据这个对象的perm属性给其授权
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal(); //授权
info.addStringPermission(currentUser.getPerm()); return info;
}
三、涉及到的主要代码
ShiroConfig.java
- 有三病(Bean),分别代表Shiro三核心,Bean1负责给请求设置权限
package com.config;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig{
//shriofilterbean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//关联securityManager
bean.setSecurityManager(securityManager);
//给请求设置权限
Map<String,String> filter = new LinkedHashMap<>();
filter.put("/user/information","perms[user:gr]");
filter.put("/user/recommend","perms[user:tj]");
filter.put("/","anon");
bean.setFilterChainDefinitionMap(filter);
//当没有登陆时,跳转到此登陆界面
bean.setLoginUrl("/tologin");
//当没有权限时,跳转到此登陆界面
bean.setUnauthorizedUrl("/noautho");
return bean;
}
//securityManager
@Bean
public DefaultWebSecurityManager securityManager(@Qualifier("realm") UserRealm realm){
System.out.println("@securityManager");
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(realm);
return securityManager;
}
//realm
@Bean
public UserRealm realm(){
System.out.println("@realm");
return new UserRealm();
}
}
UserRealm.java
- 两方法,一给用户授权,一给登陆认证
package com.config;
import com.pojo.User;
import com.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
//自定义的realm
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("@授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前登陆的这个对象,根据这个对象的perm属性给其授权
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal();
//授权
info.addStringPermission(currentUser.getPerm());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//先取令牌
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
//根据令牌信息从数据库中取出用户
User user = userService.getUserByEmail(token.getUsername());
if(user==null){
return null; //返回null,则抛出无用户名的异常
}
//验证密码,Shiro自动验证,只需要把数据库的密码传过去就好了
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
RouterController.java
- 负责接收请求,所有的请求接口都在这
package com.controller;
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.omg.CosNaming.NamingContextExtPackage.StringNameHelper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class RouterController {
@RequestMapping({"/","/index"})
public String toWelcome(){
return "index";
}
@RequestMapping("/user/information")
public String toInformation(){
return "user/information";
}
@RequestMapping("/user/recommend")
public String toRecommend(){
return "user/recommend";
}
@RequestMapping("/tologin")
public String toLogin(){
return "login";
}
@RequestMapping("/login")
public String login(String usr, String pwd, Model model){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登陆数据,生成令牌
UsernamePasswordToken token = new UsernamePasswordToken(usr,pwd);
//用令牌登陆,如果没有异常则登陆成功
try{
subject.login(token);
//无异常则登陆成功
return "index";
}catch(UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch(IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
@RequestMapping("/noautho")
@ResponseBody
public String toNoautho(){
return "没有权限访问!";
}
}
Shiro+Mybatis实现登录认证、授权功能的更多相关文章
- Django 中自定义用户模型及集成认证授权功能总结
1. 概述 Django 中的 django.contrib.auth 应用提供了完整的用户及认证授权功能. Django 官方推荐基于内置 User 数据模型创建新的自定义用户模型,方便添加 bir ...
- springboot,vue,shiro整合 关于登录认证功能
首先是session问题 传统session认证 http协议是一种无状态协议,即浏览器发送请求到服务器,服务器是不知道这个请求是哪个用户发来的.为了让服务器知道请求是哪个用户发来的,需要让用户提供用 ...
- SpringBoot整合shiro实现用户的认证授权
* 项目环境搭建 * 配置ShiroConfig,用于shiro的基本配置和注入自定义规则 * 实现自定义的realm,继承AuthorizingRealm * 编写测试controller和页面 基 ...
- shiro 实现 网站登录记住我功能 学习记录(四)
在很多网站都有在登录的时候,比如说记住我 几天之内 只要再此打开这个网站,都不需要再登录的情况: 1.前台JSP增加 单选框:记住我 如 2.在处理登录的 Controller 代码中增加接收这个参 ...
- Shiro学习笔记 三(认证授权)
第一种首先基于角色的权限控制 1.由于不断的创建SecurityFactory工程等步骤重复多次,所以应该将这些步骤封装成一个工具类 还是首先看一下目录结构 主要用到文件 首先贴一下工具类的方法 pa ...
- Cassandra的登录认证授权
cassandra的登录验证机制是独自的,数据是集群共享的 参考:http://blog.csdn.net/y_y_y_k_k_k_k/article/category/5943357 1.初始安装启 ...
- 【项目实践】一文带你搞定Session和JWT的登录认证方式
以项目驱动学习,以实践检验真知 前言 登录认证,估计是所有系统中最常见的功能了,并且也是最基础.最重要的功能.为了做好这一块而诞生了许多安全框架,比如最常见的Shiro.Spring Security ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_10-前端集成认证授权-需求分析
4 前端集成认证授权 4.1 需求分析 截至目前认证授权服务端的功能已基本完成,本章实现前端集成认证授权功能. 前端集成认证授权功能需要作如下工作: 1.前端页面校验用户的身份,如果用户没有登录则跳转 ...
- Vue结合Django-Rest-Frameword结合实现登录认证(一)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/2436173500265335 微信公众 ...
随机推荐
- 基于udp协议的套接字通信
服务端: import socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(('127.0.0.1',8 ...
- php json接口demo
<?php class Student { public $no; public $username; public $password; } $student=new Student(); $ ...
- 打印js对象内容
function writeObj(obj){ var description = ""; for(var i in obj){ var property=obj[i]; desc ...
- Windows SDK 的 ctype.h 里有一些有用的函数,例如字符串的大小写转换
#define _tolower(c) ((c) - 'A' + 'a') #define _toupper(c) ((c) - 'a' + 'A')
- [redis]SDS和链表
一.SDS 1.SDS结构体 redis3.2之前:不管buf的字节数有多少,都用 4字节的len来储存长度,对于只存短字符串那么优点浪费空间,比如只存 name,则len=4 则只需要一个字节8位即 ...
- Spring5参考指南: BeanWrapper和PropertyEditor
文章目录 BeanWrapper PropertyEditor BeanWrapper 通常来说一个Bean包含一个默认的无参构造函数,和属性的get,set方法. org.springframewo ...
- .net多线程归并排序
一.概述 在了解排序算法的同时,想到用多线程排序减少排序的时间,所以写了一个简单的示例,加深印象.下面是具体代码 二.内容 环境:vs2017,.net core 2.2 控制台程序. 运行时使用r ...
- Springboot中,Tomcat启动war包的流程
将一个SpringBoot项目,打成war包 <!-- 1. 修改POM依赖 --> <dependency> <groupId>org.springframewo ...
- Django入门4: ORM 数据库操作
大纲 一.DjangoORM 创建基本类型及生成数据库表结构 1.简介 2.创建数据库 表结构 二.Django ORM基本增删改查 1.表数据增删改查 2.表结构修改 三.Django ORM 字段 ...
- Leetcode---Solutions&Notes
Leetcode已经成为面试必备技能之一,为了紧随潮流,也模仿大佬们刷刷题. 1.采用"龟系"做法,每道题尽量做到时间复杂度和空间复杂度的较优水平: 2.每道题的Solution先 ...