springboot整合shiro详细介绍

1:创建springboot项目路径如下

在这里插入图片描述

2:pom.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springbootshiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootshiro</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring.shiro.version>1.6.0</spring.shiro.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${spring.shiro.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--页面模板依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--热部署依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3:创建三个bean,Permissions,Role,User

@Data
@AllArgsConstructor
public class Permissions {
    private String id;
    private String permissionsName;
}
@Data
@AllArgsConstructor
public class Role {

    private String id;
    private String roleName;
    /**
     * 角色对应权限集合
     */
    private Set<Permissions> permissions;
}

@Data
@AllArgsConstructor
public class User {
    private String id;
    private String userName;
    private String password;
    private String mobile;
    private String email;
    /**
     * 用户对应的角色集合
     */
    private Set<Role> roles;
}

4:创建controller

@RestController
@Slf4j
public class LoginController {

    @GetMapping("/login")
    public String login(User user) {
        if (!StringUtils.hasLength(user.getUserName()) || !StringUtils.hasLength(user.getPassword())) {
            return "请输入用户名和密码!";
        }
        //用户认证信息
        Subject subject = SecurityUtils.getSubject();
        if(!subject.isAuthenticated() && !subject.isRemembered()) {
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                    user.getUserName(),
                    user.getPassword()
            );
            usernamePasswordToken.setRememberMe(true);
            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";
    }

    @RequiresRoles("admin")
    @GetMapping("/admin")
    public String admin() {
        System.out.println("====admin========");
        return "admin success!";
    }


    @RequiresPermissions("add")
    @GetMapping("/add")
    public String add() {
        System.out.println("====add========");
        return "add success!";
    }



    @GetMapping("/tologout")
    @RequiresGuest
    public String logout() {
        System.out.println("====logout========");
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "logout success!";
    }
}

5:创建service和impl

public interface LoginService {
    User getUserByName(String getMapByName);
    User getUserByMobile(String getMapByMobile);
    User getUserByEmail(String getMapByEmail);
}

@Service
public class LoginServiceImpl implements LoginService {


    /**
     * 模拟数据库查询
     * @param mobile 电话号码
     * @return User
     */
    @SneakyThrows
    @Override
    public User getUserByMobile(String mobile) {
        User user=null;
        List<User> map=getMap();
        List<User> users=map.stream().filter(usera->usera.getMobile().equals(mobile)).collect(Collectors.toList());
        if (null !=users && users.size()>0) {
            user=users.get(0);
        }
        return user;
    }


    /**
     * 模拟数据库查询
     * @param email 邮箱
     * @return User
     */
    @SneakyThrows
    @Override
    public User getUserByEmail(String email) {
        User user=null;
        List<User> map=getMap();
        List<User> users=map.stream().filter(usera->usera.getEmail().equals(email)).collect(Collectors.toList());
        if (null !=users && users.size()>0) {
            user=users.get(0);
        }
        return user;
    }

    /**
     * 模拟数据库查询
     * @param userName 用户名
     * @return User
     */
    @Override
    public User getUserByName(String userName) {
        User user=null;
        List<User> map=getMap();
        List<User> users=map.stream().filter(usera->usera.getUserName().equals(userName)).collect(Collectors.toList());
        if (null !=users && users.size()>0) {
//                user=(User)BeanUtils.cloneBean(users.get(0));
                user=users.get(0);
        }

        return user;
    }

    private List<User> getMap(){
        Permissions permissions1 = new Permissions("1", "query");
        Permissions permissions2 = new Permissions("2", "add");
        Set<Permissions> permissionsSet = new HashSet<>();
        permissionsSet.add(permissions1);
        permissionsSet.add(permissions2);
        Role role = new Role("1", "admin", permissionsSet);
        Set<Role> roleSet = new HashSet<>();
        roleSet.add(role);
        User user = new User("1", "lisi", "42e6bf42ff7204ea6635698494c4111e","13800000000","88888888", roleSet);
        List list=new ArrayList<>();
        list.add(user);

        Set<Permissions> permissionsSet1 = new HashSet<>();
        permissionsSet1.add(permissions1);
        Role role1 = new Role("2", "user", permissionsSet1);
        Set<Role> roleSet1 = new HashSet<>();
        roleSet1.add(role1);
        User user1 = new User("2", "zhangsan", "42e6bf42ff7204ea6635698494c4111e","13900000000","99999999", roleSet1);
        list.add(user1);
        return list;
    }

}

6:创建三个shiro的realm

1:用户reaml

public class MyRealm extends AuthorizingRealm {

    @Autowired
    private LoginService loginService;

    /**
     * @MethodName doGetAuthorizationInfo
     * @Description 权限配置类
     * @Param [principalCollection]
     * @Return AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String name = (String) principalCollection.getPrimaryPrincipal();
        //查询用户名称
        User user = loginService.getUserByName(name);
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (Role role : user.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            //添加权限
            for (Permissions permissions : role.getPermissions()) {
                simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
            }
        }
        return simpleAuthorizationInfo;
    }

    /**
     * @MethodName doGetAuthenticationInfo
     * @Description 认证配置类
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
            return null;
        }
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        User user = loginService.getUserByName(name);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(),new SimpleByteSource("salt") ,getName());
            return simpleAuthenticationInfo;
        }
    }
}

2:邮箱realm

public class EmailRealm extends AuthenticatingRealm {

    @Autowired
    private LoginService loginService;


    /**
     * @MethodName doGetAuthenticationInfo
     * @Description 认证配置类
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
            return null;
        }
        //获取用户信息
        String email = authenticationToken.getPrincipal().toString();
        User user = loginService.getUserByEmail(email);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(email, user.getPassword().toString(),new SimpleByteSource("salt"), getName());
            return simpleAuthenticationInfo;
        }
    }
}


3:电话realm

public class MobileRealm extends AuthenticatingRealm {

    @Autowired
    private LoginService loginService;

    /**
     * @MethodName doGetAuthenticationInfo
     * @Description 认证配置类
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
            return null;
        }
        //获取用户信息
        String mobile = authenticationToken.getPrincipal().toString();
        User user = loginService.getUserByMobile(mobile);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(mobile, user.getPassword().toString(),new SimpleByteSource("salt"), getName());
            return simpleAuthenticationInfo;
        }
    }
}

7:主要的配置文件config,shiro必须会三步骤,三板斧设置

1:Realms 代表资源(Realms)
2:SecurityManager 流程控制(DefultSecurityManager)
3:ShiroFilterFactoruBean 请求过滤器(ShiroFilterFactoruBean)

@Configuration
public class ShiroConfig {

    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
     * LifecycleBeanPostProcessor 是管理shiro生命周期的,不直接跟权限注解关联。所以加上DefaultAdvisorAutoProxyCreator 这个bean就可以了
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     *
     * @return
     */
    @Bean
    //LifecycleBeanPostProcessor 是管理shiro生命周期的
    //这个方法不加也可以 但是网上别的博客都说需要加
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    //AuthorizationAttributeSourceAdvisor 的作用是匹配所有类 匹配所有加认证注解的方法
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    //将自己的验证方式加入容器
    @Bean
    public MyRealm myShiroRealm() {
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }

    @Bean
    public MobileRealm mobileRealm() {
        MobileRealm mobileRealm = new MobileRealm();
        return mobileRealm;
    }
    @Bean
    public EmailRealm emailRealm() {
        EmailRealm emailRealm = new EmailRealm();
        return emailRealm;
    }

    //权限管理,配置主要是Realm的管理认证sets
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		//密码加密
        HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("MD5");
        matcher.setHashIterations(6);
        myShiroRealm().setCredentialsMatcher(matcher);
        mobileRealm().setCredentialsMatcher(matcher);
        emailRealm().setCredentialsMatcher(matcher);
      //securityManager.setRealms(Arrays.asList(myShiroRealm(),mobileRealm(),emailRealm()));

		//多realm数据源认证
        ModularRealmAuthenticator authenticator =new ModularRealmAuthenticator();
        authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        authenticator.setRealms(Arrays.asList(myShiroRealm(),mobileRealm(),emailRealm()));
        securityManager.setAuthenticator(authenticator );

		//授权的缓存设置,第一次访问需要授权,后面访问跳过doGetAuthorizationInfo授权方法
        MemoryConstrainedCacheManager cacheManager=new MemoryConstrainedCacheManager();
        securityManager.setCacheManager(cacheManager);
		//设置记住我的时
        CookieRememberMeManager rememberMeManager=new CookieRememberMeManager();
        Cookie cookie=new SimpleCookie("rememberMe");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(300);//设置时长单位为秒
        rememberMeManager.setCookie(cookie);
        securityManager.setRememberMeManager(rememberMeManager);
        
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
		//anon是不需要认证的接口
        map.put("/tologout", "anon");

        //对所有用户认证
        map.put("/**", "authc");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }
}

8:手动设置初次注册密码加密落库

public class Demo {
    public static void main(String[] args) {
        //密码加密
        String password="123456";
        SimpleHash simpleHash=new SimpleHash("MD5",password,new SimpleByteSource("salt"),6);
        System.out.println(simpleHash);

    }
}

9:创建MyExceptionHandler类

当使用shiro提供的注解,实现方级别的权限控制,
@RequestGuest //表示未登录的用户可以访问,登录用户不可以访问
@RequestAuthentication //需要完成用户登录
@RequeUser //需要完成用户登录并且完成了记住我功能
@RequestPermissions //表示有相应资源和权限
@RequestRoles //需要相应的角色
需要错误补偿机制(不然捕获不了异常):没有权限就抛出异常(自定义MyExceptionHandle在类上加上@RestControllerAdvice)

@ControllerAdvice
@Slf4j
public class MyExceptionHandler {

	//@ExceptionHandler(AuthenticationException.class)
    @ExceptionHandler
    @ResponseBody
    public String ErrorHandler(AuthorizationException e) {
        log.error("没有通过权限验证!", e);
        return "没有通过权限验证!";
    }
}

以下是shiro知识笔记

1:shiro主要有三大功能模块

1: Subject:主体,一般指用户。
2: SecurityManager:安全管理器,管理所有Subject,可以配合内部安全组件。(类似于SpringMVC中的DispatcherServlet)
3: Realms:用于进行权限信息的验证,一般需要自己实现。

2:shiro QuickStart

//获得当前用户主体
Subjec currentUser=SecurityUtils.getSubject();
//判断是否完成认证,返回的是boolean
currentUser.isAuthenticated();
//认证 user前端传过来的账号密码
UsernamePasswordToke token=new UsernamePasswordToke(user.getName(),user.getPassword())
currentUser.login(token);//通过抛出的异常来判断用户结果
Session session=currentuser.getSession();
session.setAttribute(“curenUser”,currentuser.getPrincipal());
//获取用户名
String name=token.getPrincipal();
//授权
currentUser.hasRole(“role”);
currentUers.isPermitted(permission);

//登出
currentUser.logout();

3:认证流程

1:获取当前用户
2:根据当前用户获取数据库中得用户信息
3:当前用户和数据库中的用户进行密码匹配shiro会在后面帮我们进行密码比较(SimpleAuthenticationInfo*)

4:实现登录验证功能

1:创建自己的Realmd对象,继承AuthorizingReamls,然后实现重写父类的doGetAuthenticationInfo认证方法和doGetAuthorizationInfo授权方法
2:配置路径过滤器,anno,anth,authc,perms,role
Map<String,String> filterMap=new HashMap<>();
//key是ant路径,支持**代表多级路径,*代表单级,?代表当字符
//value配置shiro的默认过滤器,可以查看DefaultFilter类查看过滤器类型。注意:过滤器是有顺序的,谁在前面就生效谁
filterMap.put(“”,“anno”);//表示不拦截(要放在authc前面)
filterMap.put(“”,“authc”);//表示拦截,要登录才可以访问

5:修复登录认证错误的访问情况

//设置登录页(未登录访问资源的时候会跳转到登录页)
factoryBean.setLoginurl(“/tologin”)
//登录成功页,
//未经授权页
factoryBean.setUnauthorizedUrl(“/tologin”)

6:登出的两种方式

//第一种方式
@RequestMapp(“/tologgout”)
public void logout(){
Subject currentUser=SecurityUtils.getSubeject();
currentUser.loggout();
}
//第二种方式
直接配置shiro提供的过滤器,有这个请求的时候直接退出
filterMap.put(“/tologgout”,“logout”)

list中map转对象的方法,BeanUtils.cloneBean(list)

7:实现授权功能

//在MyRealm类中的doGetAuthorizationInfo授权方法操作
1:获取当前用户
2:绑定角色,资源

硬编码的方式,自行判断权限,判断是否有权限和角色
1:判断这个请求是否有这个permission权限
@RequestMapping(“/permission”)
Subject currentUser=SecurityUtils.getSubeject();
if(currentUers.isPermitted(“permission”)){
//TODO
};
2:判断这个请求是否有这个radmin角色
@RequestMapping(“/permission”)
Subject currentUser=SecurityUtils.getSubeject();
if(currentUers.hasRole(“admin”)){
//TODO
};

使用shirot提供的perms,roles过滤器,集中配置权限信息
//在路径拦截器中配置,同时配置没有权限跳转路径
filterMap.put(“/add/*”,“authc,perms[add,del],roles[admin]”);
factoryBean.setUnAuthorizedUrl(“/unauthorized”)
//错误补偿机制:没有权限就会进入ShiroFilterFactoryBean中配置的UnAuthorizedUrl

使用shiro提供的注解,实现方级别的权限控制
//错误补偿机制:没有权限就抛出异常(自定义MyExceptionHandle在类上加上@RestControllerAdvice,在 方法上加上@ExceptionHandler(AuthenticationException.class))
@RequestGuest //表示未登录的用户可以访问,登录用户不可以访问
@RequestAuthentication //需要完成用户登录
@RequeUser //需要完成用户登录并且完成了记住我功能
@RequestPermissions //表示有相应资源和权限
@RequestRoles //需要相应的角色

8: 密码加密

shiro会获取一个CredentialsMatch对象,来对密码进行比对
想要用MD5方式进行加密:
//在shiroConfig类中的SecurityManager流程控制中添加
HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
matcher.setHashAlgorithmName(“MD5”);
matcher.setHashIterations(3);
myRealm.setCredentialsMatcher(matcher);
MdCredentialsMatc已经过期,要使用HashedCredentialsMatch并设定算法名。
HashedCredentialsMatch
String hashAlgorithm,对于Hash接口的实现类。MD5
int hashIterations Hash迭代次数
boolean hashSalted 已过时,不用设置
boolean storedCredentialsHexEncoded 设置默认的true
加盐加密:
需要在认证返回的认证信息SimpleAuthenticationInfo中,指定需要加的盐salt,这样算出来的密文才可以和数据库中的密文进行比对
初次注册对密码落库加密
SimpleHash simpleHash=newSimpleHash(“MD5”,ByteSource.Util.bytes(password),ByteSource.Util.bytes(“salt”),3);
注意:字符串转ByteSource对象,ByteSource source=ByteSource.Util.bytes(“salt”);

9:多realm数据源认证

实现登录名,手机号,邮箱都可以登录功能
可以定义多个Realm完成不同的登录功能
我们通过增加一个phoneRealm,就实现了手机号登录的功能
1:创建PhoneRealm继承AuthenticatingRealm,只需要认证就行,在MyReaml中已经实现过授权
2:在PhoneRealm中重写doGetAuthenticationInfo方法,可照搬MyRealm中的doGetAuthenticationInfo方法,修改一下获取用户名改为获取电话就行
3:三板斧的SecurityManger在流程控制的方法参数添加AuthenticatingRealm phoneRealm;
方法体中设置加密规则;
DefultSecurityManager securityManager=new DefultSecurityManager();
HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
matcher.setHashAlgorithmName(“MD5”);
matcher.setHashIterations(3);
myRealm.setCredentialsMatcher(matcher);//这是用户名Reaml
phoneRealm.setCredentialsmatch(matcher);//这是电话号码的Reaml
securityManager.setReamls(Arrays.asList(myRealm,phoneRealm))//可以做一个或者集合

4:多Realm的认证策略:
AuthenticationStrategy接口有三个实现类
AllSuccessfulStrategy:需要所以Realm认证成功,才能最终认证成功
AtLeastOneSuccessfulStrategy:(默认策略)至少有一个Realm认证成功,才能最终认证成功
FirstSuccessfulStrategy:第一个Realm认证成功后即返回认证成功,不再进行后面的Realm认证
设置认策略:在三板斧的SecurityManger在流程控制的设置
ModularRealmAuthenticator authenticator =new ModularRealmAuthenticato();
authenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
authenticator.setRealms(Arrays.asList(myRealm,phoneRealm));
securityManager.setAuthenticator(authenticator );

10:下面这两个是要在分布式部署中实现状态共享需要改造的地方

1:记住我功能

遇到的坑,调试了一个下午
1:记住我功能是在本地浏览器生成cookie保存的
2:subject.isAuthenticated()和subject.isRemembered()同时只能一个为true
3:subject.isAuthenticated()保存的的是session,seesion有就会当浏览器已关闭seesion就没有了,subject.isRemembered()保存的是cookie,cookie可以设置存活时长,保存在浏览器本地,关闭浏览器不会取消,到期才会取消。也可以设置cookie时间为cookie.setMaxAge(60),默认是-1 关闭浏览器失效。
3:第一次访问的成功登录后,只要不关闭浏览器isAuthenticated()一直为true
4:关闭浏览器重启打开,去登陆判断的时候subject.isAuthenticated()就会为false,subject.isAuthenticated()根据cookie存活在为true,否则为false
5:使用shiro注解生效一定要在shiroConfig注入三个bean,才能管理shiro注解生命周期,LifecycleBeanPostProcessor,DefaultAdvisorAutoProxyCreator,AuthorizationAttributeSourceAdvisor
6:使用记住我功能是为了没有session通过cookie访问资源,可以在shiroFilterFactoryBean中配置("/pass/", “user”),或者直接在方法上加上注解@RequiresUser(不知为何这个注解一直不生效,所以用@RequiresPermissions(pass:)同样可实现一样的功能)

UsernamePasswordToke token=new UsernamePasswordToke(user.getName(),user.getPassword());
token.isRememberMe();//是否记住我
token.setRemembeMe(true);
记住我功能对应了默认的user过滤器(就是需要记住我user过滤器才生效,如果没有记住我,就是登录了也不生效)
设置记住我时长和保存在哪里
三板斧的SecurityManger在流程控制的方法中设置
CookieRememberMeManager rememberMeManager=new CookieRememberMeManager();
Cookie cookie=new SimpleCookie(“rememberMe”);
cookie.setHttpOnly(true);
cookie.setMaxAge(5);//设置时长单位为秒
rememberMeManager.setCookie(cookie);
securityManager.setRememberMeManager(rememberMeManager);

多服务器之间怎么共享cookie和sesion,访问一定是通过nginx进行负载均衡的,所以可以在nginx安装redis进行数据共享cookie和sesion,还有一种是直接落库到数据库,但是这样方式耗性能

2:回话管理

使用和cookie设置类似
securityManager.setSessionManager(sessionManager);

3:认证缓存(认同通过后,后面就不进认证器查数据了)

MemoryConstrainedCacheManagercacheManager=new MemoryConstrainedCacheManager();
securityManager.setCacheManager(cacheManager);

记住我,会话管理以及认证缓存,都可以通过扩展对应的manager接口的方式,实现自己的灵活扩展,比如将信息共享到redis

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值