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">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.3.4.RELEASE

com.java

shiro-service

1.0-SNAPSHOT

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.apache.shiro

shiro-spring

1.6.0

org.springframework.boot

spring-boot-starter-aop

org.projectlombok

lombok

true

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.2

mysql

mysql-connector-java

5.1.6

com.alibaba

druid

1.1.4

org.springframework.boot

spring-boot-starter-thymeleaf

org.springframework.boot

spring-boot-devtools

runtime

org.springframework.boot

spring-boot-maven-plugin

  

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})

  

 

  

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 permissions;

}

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 roles;

}

  

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 findPermission(Integer roleId);

int addBatchPermission(List permissions);

}

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 findRoleById(Integer id);

@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> getList();

List getListByBean();

}

  

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 = roleMapper.findRoleById(user.getId());

roleByName.forEach(role -> {

List permissionList = permissionMapper.findPermission(role.getId());

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 = roleMapper.findRoleById(byName.getId());

roleById.forEach(r->{

Integer rId = r.getId();

List permissions=new ArrayList<>();

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 = new HashMap();

//登出

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

  

 

相关链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。