导入依赖
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-spring-boot-web-starterartifactId>
- <version>1.12.0version>
- dependency>
配置类
- package com.qf.shiro2302.config;
-
- import com.qf.shiro2302.entity.User;
- 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.realm.Realm;
- import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
- import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import java.util.Arrays;
- import java.util.List;
-
- @Configuration
- @Slf4j
- public class ShiroConfig {
-
-
-
- @Bean
- public Realm realm(){
- AuthorizingRealm authorizingRealm = new AuthorizingRealm() {
-
- /**
- *
- * @param token 这的token就是调用login方法时,传入的token对象
- * @return AuthenticationInfo 对象中,封装了用户的身份信息(principals),密码(credentials),提供信息的realm的名字
- * @throws AuthenticationException
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- System.out.println("===========获取身份信息===============");
- //查询数据库获取当前用户名对应的User对象
- String username = (String) token.getPrincipal();
- System.out.println("username="+username);
- System.out.println("this.getName()={}"+this.getName());
- User user=getUserFromDB(username);
-
- //需要返回shiro规定的AuthenticationInfo类型的对象
- //这个对象中,包含了用户的身份认证信息
- // SimpleAuthenticationInfo的构造函数中的第一个参数,principals代表用户的身份信息
- // 一般可以使用 user对象,或者使用用户名也可以
- // 第三个参数,代表当前realm的名字,固定写法
- //Authentication 证明的意思
- SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
-
- return authenticationInfo;
- }
-
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
- System.out.println("============获取授权===============");
-
- // 从数据库表中查询当前用户具有的角色和权限字符串
- User user = (User) principalCollection.getPrimaryPrincipal();
-
- List
roles= getRolesFromDB(user); - List
permissions= getPermissionFromDB(user); -
- // 按照约定返回AuthorizationInfo对象
- SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
- // 放入从数据库中查询到的当前用户的角色信息
- // authorizationInfo.addRole("test");
- authorizationInfo.addRoles(roles);
-
- // 放入从数据库中查询到的当前用户的权限信息
- // authorizationInfo.addStringPermission("document:read");
- authorizationInfo.addStringPermissions(permissions);
- return authorizationInfo;
- }
- };
-
-
- return authorizingRealm;
-
-
- }
-
- private List
getRolesFromDB(User user) { - return Arrays.asList("test","admin");
- }
-
- private List
getPermissionFromDB(User user) { - return Arrays.asList("document:read","document:write");
- }
-
- private User getUserFromDB(String username) {
- User user = new User(100, "数据库用户", "123456", "123@qq.com");
- return user;
- }
-
- @Bean
- public ShiroFilterChainDefinition shiroFilterChainDefinition() {
- //ShiroFilterChainDefinition 此接口就一个实现类 默认Shiro过滤器链定义类
- DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
-
- // 让登录接口直接被shiro的过滤器放行
- //第一个参数:接口的路径
- //第二个参数:shiro内部的过滤器的名字,anon代表无需登录即可访问的特殊的过滤器,注意过滤器的名字是固定的,不能乱写
- chainDefinition.addPathDefinition("/login/dologin", "anon");
- // 放行springboot的错误页面的请求url 这个页面就是个response拼接的页面
- chainDefinition.addPathDefinition("/error", "anon");
-
-
- //增加角色或者权限,对于某些请求
- // logged in users with the 'test' role
- // chainDefinition.addPathDefinition("/test/**", "authc, roles[test,admin], perms[document:read,document:write]"); 这个如果改成anon,就不能加后面的角色或者权限,否则,将会被认为需要登录,重定向到登录页
-
- // all other paths require a logged in user
- chainDefinition.addPathDefinition("/**", "authc");
- return chainDefinition;
- }
- }
调用接口
- package com.qf.shiro2302.controller;
-
- import lombok.extern.slf4j.Slf4j;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.AuthenticationToken;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- @RequestMapping("/login")
- @Slf4j
- public class LoginController {
-
- @PostMapping("/dologin")
- public String dologin(String username,String password){
-
- //使用Shiro进行登录处理
- Subject subject = SecurityUtils.getSubject();//获取shiro核心对象
- //为了调用shiro的登录方法,需要准备一个Token对象
- UsernamePasswordToken token = new UsernamePasswordToken(username,password);
- System.out.println(token);
- subject.login(token);//使用shiro登录流程
-
- return "登陆成功 ";
-
-
- }
-
- }
获取ShiroSession中的用户,注解添加权限
- package com.qf.shiro2302.controller;
-
- import com.qf.shiro2302.entity.User;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authz.annotation.RequiresPermissions;
- import org.apache.shiro.authz.annotation.RequiresRoles;
- import org.apache.shiro.subject.Subject;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- @RequestMapping("/test")
- public class TestController {
-
-
- @RequiresRoles({"test","admin"})
- @RequiresPermissions({"document:read","document:write"})
- @RequestMapping("/test1")
- public String hello1(){
- return "hello shiro !!!";
- }
-
-
- @RequestMapping("/test2")
- public User hello2(){
- //如果使用shiro获取当前登录用户的身份信息
- Subject subject = SecurityUtils.getSubject();
- User principal = (User) subject.getPrincipal();
- System.out.println(principal);
- return principal;
- }
- }
- shiro:
- loginUrl: /login.html
- #配置没登陆的时候重定向的页面。这个请求是可以放行的
1.配置类
- package com.qf.shiroHomework.config;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.qf.shiroHomework.entity.*;
- import com.qf.shiroHomework.mapper.TPersMapper;
- import com.qf.shiroHomework.mapper.TRoleMapper;
- import com.qf.shiroHomework.mapper.TRolePermsMapper;
- import com.qf.shiroHomework.mapper.TUserRoleMapper;
- import com.qf.shiroHomework.service.ITUserService;
- 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.authc.credential.HashedCredentialsMatcher;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.authz.SimpleAuthorizationInfo;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.realm.Realm;
- import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
- import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.util.ByteSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Collectors;
- import java.util.stream.IntStream;
-
- @Configuration
- @Slf4j
- public class ShiroConfig {
-
- @Autowired
- private ITUserService itUserService;
- @Autowired
- private TUserRoleMapper tUserRoleMapper;
- @Autowired
- private TRolePermsMapper tRolePermsMapper;
- @Autowired
- private TPersMapper tPersMapper;
- @Autowired
- private TRoleMapper tRoleMapper;
-
- //将Realm对象放入IOC容器里
- @Bean
- public Realm realm(){
- AuthorizingRealm authorizingRealm = new AuthorizingRealm() {
-
- /**
- *
- * @param token 这的token就是调用login方法时,传入的token对象
- * @return AuthenticationInfo 对象中,封装了用户的身份信息(principals),密码(credentials),提供信息的realm的名字
- * @throws AuthenticationException
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- System.out.println("===========获取身份信息===============");
- //获取身份信息
- String username = (String) token.getPrincipal();
-
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("username",username);
- TUser user = itUserService.getOne(wrapper);
-
- // 需要返回shiro规定的AuthenticationInfo类型的对象
- // 这个对象中,包含了用户的身份认证信息
- // SimpleAuthenticationInfo的构造函数中的第一个参数,principals代表用户的身份信息
- // 一般可以使用 user对象,或者使用用户名也可以
- // 第三个参数: 盐
- // 第四个参数,代表当前realm的名字,就是一个标识,标识是这个Bean调用的这个方法,没有作用,固定写法
-
- SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
-
- return authenticationInfo;
- }
-
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
- TUser user = (TUser) principalCollection.getPrimaryPrincipal();
- SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
- log.info("用户角色={}",getRolesFromDB(user));
- log.info("用户权限={}",getPermissionFromDB(user));
- authorizationInfo.addRoles(getRolesFromDB(user));
- authorizationInfo.addStringPermissions(getPermissionFromDB(user));
- return authorizationInfo;
- }
- };
-
- // 把HashedCredentialsMatcher对象设置到authorizingRealm对象中
- authorizingRealm.setCredentialsMatcher(hashedCredentialsMatcher());
-
- return authorizingRealm;
- }
-
-
- @Bean
- public HashedCredentialsMatcher hashedCredentialsMatcher(){
-
- HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
- //设置算法名称
- matcher.setHashAlgorithmName("md5");
- //设置hash次数
- matcher.setHashIterations(1024);
- return matcher;
-
-
- }
-
-
-
-
- //配置Shiro过滤器链
- @Bean
- public ShiroFilterChainDefinition shiroFilterChainDefinition(){
- DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
- chainDefinition.addPathDefinition("/register.html","anon");
- chainDefinition.addPathDefinition("/error/500.html","anon");
- chainDefinition.addPathDefinition("/error","anon");
- chainDefinition.addPathDefinition("/user/register","anon");
- chainDefinition.addPathDefinition("/user/login","anon");
- chainDefinition.addPathDefinition("/user/**","authc");
- chainDefinition.addPathDefinition("/**","authc");
-
-
- return chainDefinition;
-
- }
-
- public List
getPermissionFromDB(TUser user) { - if (user.getPerms()!=null){
- return user.getPerms();
- }
-
-
- Integer id = user.getId();
- //通过用户ID找到角色
-
- QueryWrapper
wrapper1 = new QueryWrapper<>(); - wrapper1.eq("userid",id);
- TUserRole tUserRole = tUserRoleMapper.selectOne(wrapper1);
- Integer roleid = tUserRole.getRoleid();
- System.out.println(roleid);
-
-
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.select("permsid").eq("roleid",roleid);
- List
- System.out.println(permsidList);
- List
integers = permsidList.stream().map(o -> { - return (Integer) o;
- })
- .collect(Collectors.toList());
- List
tPers = tPersMapper.selectBatchIds(integers); - System.out.println(tPers);
- ArrayList
strings = new ArrayList<>(); - for (TPers tPer : tPers) {
- strings.add(tPer.getName());
- }
- user.setPerms(strings);
-
- return strings;
- }
-
- public List
getRolesFromDB(TUser user) { -
- if (user.getRoleName()!=null){
- return user.getRoleName();
- }
-
- Integer id = user.getId();
- //通过用户ID找到角色
- QueryWrapper
wrapper1 = new QueryWrapper<>(); - wrapper1.eq("userid",id);
- TUserRole tUserRole = tUserRoleMapper.selectOne(wrapper1);
- Integer roleid = tUserRole.getRoleid();
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.select("name").eq("id",roleid);
- List
- List
strings = roles.stream().map(o -> { - return (String) o;
- })
- .collect(Collectors.toList());
- user.setRoleName(strings);
- return strings;
- }
-
- }
- package com.qf.shiroHomework.entity;
-
- import com.baomidou.mybatisplus.annotation.IdType;
- import com.baomidou.mybatisplus.annotation.TableField;
- import com.baomidou.mybatisplus.annotation.TableId;
- import com.baomidou.mybatisplus.annotation.TableName;
- import java.io.Serializable;
- import java.util.List;
-
- import lombok.*;
-
- /**
- *
- *
- *
- *
- * @author jmj
- * @since 2023-08-10
- */
- @NoArgsConstructor
- @AllArgsConstructor
- @Data
- @TableName("t_user")
- public class TUser implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
-
- private String username;
-
- private String password;
-
- private String salt;
-
- @TableField(exist = false) // 说明当前这个属性在数据库表中没有对应的字段,让mp生成sql时忽略这个属性
- private List
roleName; - @TableField(exist = false)
- private List
perms; -
-
-
-
- }
Controller
- //复杂密码匹配器
- @PostMapping("/login")
- public String login(TUser user){
- //使用Shiro进行登录处理
- Subject subject = SecurityUtils.getSubject();//获取shiro核心对象
- //为了调用shiro的登录方法,需要准备一个Token对象
-
- UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
-
- subject.login(usernamePasswordToken);
-
- return "redirect:/show.html";
-
- }
以前手写MD5处理的方法
- // 简单密码匹配器方案
- // @PostMapping("/login")
- // public String login(TUser user){
- // //使用Shiro进行登录处理
- // Subject subject = SecurityUtils.getSubject();//获取shiro核心对象
- // //为了调用shiro的登录方法,需要准备一个Token对象
- // //添加Where 条件
- // QueryWrapper
wrapper = new QueryWrapper<>(); - // wrapper.eq("username",user.getUsername());
- // TUser u = itUserService.getOne(wrapper);
- // if (u==null){
- // return "redirect:/index.html";
- // }else {
- //
- // //MD5加密
- // Md5Hash md5Hash = new Md5Hash(user.getPassword(), u.getSalt(), 1024);
- // String newPassword = md5Hash.toHex();
- //
- //
- // UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), newPassword);
- //
- // subject.login(usernamePasswordToken);
- // }
- //
- // return "redirect:/show.html";
- //
- // }