shiro主要实现认证和授权的问题
认证确认用户身份,授权对用户访问资源的权限做控制
建表语句
CREATE TABLE `user` (
id INT(11) PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(255) COMMENT '用户名',
`password` VARCHAR(255) COMMENT '密码'
)
INSERT INTO `user`(`name`,`password`) VALUES('test','123456')
CREATE TABLE `role` (
id INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL COMMENT '主键',
role_name VARCHAR(255) DEFAULT NULL COMMENT '角色名称',
user_id VARCHAR(255) DEFAULT NULL COMMENT '用户id'
)
INSERT INTO `role`(role_name,user_id) VALUES('admin','1')
CREATE TABLE permission (
id INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL COMMENT '主键',
permission VARCHAR(255) DEFAULT NULL COMMENT '权限',
role_id VARCHAR(255) DEFAULT NULL COMMENT '角色id'
)
INSERT INTO permission(permission,role_id) VALUES
('create','1'),
('query','1')
代码部分
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
server.port=8001
logging.level.com.java=debug
logging.level.web=debug
spring.devtools.add-properties=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring_shiro?useUnicode=true&characterEncoding=utf-8&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=root
mybatis.mapper-locations=classpath:mapping/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
spring.aop.proxy-target-class=true
INSERT INTO permission(permission,role_id) VALUES
(#{item.permission},#{item.roleId})
SELECT a.`name`,a.`password`,b.`role_name`,c.`permission`
FROM `user` a INNER JOIN `role` b ON a.id=b.user_id INNER JOIN permission c ON b.id=c.role_id
package com.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author yourheart
* @Description
* @create 2022-05-03 20:30
*/
@SpringBootApplication
public class ShiroApplication {
public static void main(String[] args) {
SpringApplication.run(ShiroApplication.class,args);
}
}
package com.java.bean;
import lombok.Data;
/**
* @author yourheart
* @Description
* @create 2022-06-15 1:54
*/
@Data
public class Permission {
private Integer id;
private String permission;
private Integer roleId;
}
package com.java.bean;
import lombok.Data;
/**
* @author yourheart
* @Description
* @create 2021-09-17 23:54
*/
@Data
public class ResponseBean {
/**
* 状态码
*/
private String code;
/**
* 返回值
*/
private String msg;
/**
* 拓展字段
*/
private Object extraInfo;
}
package com.java.bean;
import lombok.Data;
import java.util.List;
/**
* @author yourheart
* @Description
* @create 2022-06-15 1:55
*/
@Data
public class Role {
private Integer id;
private String roleName;
private Integer userId;
private List
}
package com.java.bean;
import lombok.Data;
import java.util.List;
/**
* @author yourheart
* @Description
* @create 2022-06-15 1:53
*/
@Data
public class User {
private Integer id;
private String name;
private Integer password;
private List
}
package com.java.mapper;
import com.java.bean.Permission;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author yourheart
* @Description
* @create 2022-06-25 8:37
*/
@Mapper
public interface PermissionMapper {
@Select("SELECT permission FROM permission WHERE role_id=#{roleId}")
List
int addBatchPermission(List
}
package com.java.mapper;
import com.java.bean.Role;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author yourheart
* @Description
* @create 2022-06-25 8:37
*/
@Mapper
public interface RoleMapper {
@Select("SELECT * FROM `role` r WHERE user_id =#{id}")
List
@Insert("INSERT INTO `role`(role_name,user_id) VALUES(#{roleName},#{userId})")
int addRole(Role role);
}
package com.java.mapper;
import com.java.bean.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* @author yourheart
* @Description
* @create 2022-06-25 8:10
*/
@Mapper
public interface UserMapper {
@Select("SELECT * FROM `user` WHERE `name`=#{name}")
User findByName(@Param("name") String name);
@Select("SELECT COUNT(*) FROM `user` WHERE `name`=#{name} AND `password`=#{password}")
int selectUserExists(User user);
@Insert("INSERT INTO `user`(`name`,`password`) VALUES(#{name},#{password})")
int addUser(User user);
@Select("SELECT * FROM `user` WHERE id=#{id}")
User findById(Integer id);
@Select("SELECT a.`name`,a.`password`,b.`role_name`,c.`permission` \n" +
"FROM `user` a INNER JOIN `role` b ON a.id=b.user_id INNER JOIN permission c ON b.id=c.role_id")
List
List
}
package com.java.service;
import com.java.bean.ResponseBean;
import com.java.bean.User;
public interface UserService {
/**
* 通过用户名查询用户的权限
* @param name
* @return
*/
User getUserByName(String name);
/**
* 添加用户时默认给query权限
* @param user
* @return
*/
ResponseBean addUser(User user);
}
package com.java.service.impl;
import com.java.bean.Permission;
import com.java.bean.ResponseBean;
import com.java.bean.Role;
import com.java.bean.User;
import com.java.mapper.PermissionMapper;
import com.java.mapper.RoleMapper;
import com.java.mapper.UserMapper;
import com.java.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author yourheart
* @Description
* @create 2022-06-24 20:34
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleMapper roleMapper;
@Autowired
private PermissionMapper permissionMapper;
/**
* 通过用户名查询用户的权限
*
* @param name
* @return
*/
@Override
public User getUserByName(String name) {
User user = userMapper.findByName(name);
List
roleByName.forEach(role -> {
List
role.setPermissions(permissionList);
});
user.setRoles(roleByName);
return user;
}
/**
* 添加用户时默认给query权限
*
* @param user
* @return
*/
@Override
public ResponseBean addUser(User user) {
ResponseBean responseBean=new ResponseBean();
int selectUserExists = userMapper.selectUserExists(user);
if (selectUserExists==1){
responseBean.setCode("-100");
responseBean.setMsg("用户已经存在");
return responseBean;
}
//入参需要用户名和密码
int addUser = userMapper.addUser(user);
//通过用户名查询返回用户的id,向角色表中存放用户的角色和用户的id
User byName = userMapper.findByName(user.getName());
Role role=new Role();
role.setRoleName("common");
role.setUserId(byName.getId());
int addRole = roleMapper.addRole(role);
//查询角色的id,向权限表存放角色的权限和角色id
List
roleById.forEach(r->{
Integer rId = r.getId();
List
Permission permission=new Permission();
permission.setPermission("query");
permission.setRoleId(rId);
permissions.add(permission);
permissionMapper.addBatchPermission(permissions);
});
responseBean.setCode("100");
responseBean.setMsg("用户添加成功");
return responseBean;
}
}
shiro权限控制部分
package com.java.config;
import com.java.bean.Permission;
import com.java.bean.Role;
import com.java.bean.User;
import com.java.service.UserService;
import lombok.extern.slf4j.Slf4j;
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;
/**
* @author yourheart
* @Description 实现AuthorizingRealm接口用户用户认证
* @create 2022-06-15 1:56
*/
@Slf4j
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 角色权限和对应权限添加
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String name = (String) principalCollection.getPrimaryPrincipal();
log.info("【角色权限和对应权限添加】name:{}", name);
//查询用户名称
User user = userService.getUserByName(name);
log.info("【角色权限和对应权限添加】user:{}", user);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Role role : user.getRoles()) {
//添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission : role.getPermissions()) {
//添加权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
}
/**
* 用户认证
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
log.info("【用户认证】authenticationToken.getPrincipal():{}", authenticationToken.getPrincipal());
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String name = authenticationToken.getPrincipal().toString();
log.info("【用户认证】name:{}", name);
User user = userService.getUserByName(name);
log.info("【用户认证】user:{}", user);
if (user == null) {
//这里返回后会报出对应异常
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
}
}
package com.java.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SecurityManager;
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 java.util.HashMap;
import java.util.Map;
/**
* @author yourheart
* @Description
* @create 2022-06-15 1:58
*/
@Configuration
@Slf4j
public class ShiroConfiguration {
/**
* 将自己的验证方式加入容器
*
* @return
*/
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
/**
* 权限管理,配置主要是Realm的管理认证
*
* @return
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
/**
* Filter工厂,设置对应的过滤条件和跳转条件
*
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map
//登出
map.put("/logout", "logout");
/**
* Shiro内置过滤器,能够实现拦截器相关的拦截器
* 经常使用的过滤器:
* anon:无需认证(登陆)能够访问
* authc:必须认证才能够访问
* user:若是使用rememberMe的功能能够直接访问
* perms:该资源必须获得资源权限才能够访问
* role:该资源必须获得角色权限才能够访问
**/
//对所有用户认证
map.put("/**", "authc");
map.put("/re", "anon");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
/**
* 加入注解的使用,不加入这个注解不生效
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
package com.java.controller.front;
import com.java.bean.Role;
import com.java.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yourheart
* @Description
* @create 2022-06-15 2:11
*/
@RestController
@Slf4j
public class TestController {
@PostMapping("/login")
public String login(@RequestBody User user) {
if (StringUtils.isEmpty(user.getName()) || StringUtils.isEmpty(user.getPassword())) {
return "请输入用户名和密码!";
}
//用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
user.getName(),
String.valueOf(user.getPassword())
);
try {
//进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
} catch (UnknownAccountException e) {
log.error("用户名不存在!", e);
return "用户名不存在!";
} catch (AuthenticationException e) {
log.error("账号或密码错误!", e);
return "账号或密码错误!";
} catch (AuthorizationException e) {
log.error("没有权限!", e);
return "没有权限";
}
return "login success";
}
/**
* 用户登出
* @return
*/
@RequestMapping("/loginOut")
public String loginOut(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "退出成功";
}
@RequiresPermissions("query")
@RequestMapping(value = "/index")
@ResponseBody
public String index(){
return "进入主页";
}
@RequiresPermissions("create")
@GetMapping("/add")
public String add() {
return "add success!";
}
@RequestMapping(value = "/re")
@ResponseBody
public String re(){
return "进入注册页面";
}
@RequestMapping(value = "/log")
@ResponseBody
public String log(){
return "进入日志页面";
}
}
附上测试地址
http://127.0.0.1:8001/login
{
"name":"qiuxie",
"password":"123"
}
http://127.0.0.1:8001/index
http://127.0.0.1:8001/add
用户登出
http://127.0.0.1:8001/loginOut
相关链接
发表评论