【Shiro安全框架】核心概念、基本配置、整合Web项目_shiropeizhi

问题1:什么是shiro?它有什么用?
​
答:shiro是apache公司推出的一款安全框架,主要在项目中进行权限控制
核心概念
@@@@@@@shiro中的几个核心概念:
​
1、SecurityManager:安全管理器
    作用:用于执行认证(登录)、授权(获得用户的访问权限)
​
2、Subject:主体
    作用:它代表当前用户
​
3、Realm:领域对象
    作用:它用于封装认证、授权的方法
​
基本语法
阶段1:讲解shiro的基本语法 (java程序即可)
​
    1、基于ini文件的认证(登录)--把用户名和密码以文件的形式保存以后,用来验证
    2、基于realm类的认证----用户名和密码存放在数据库中,连接数据库来验证
    3、md5加密---防的是管理员
    4、基于ini文件的授权----是在ini文件中获取,用来判断用户拥有哪种角色和权限
    5、基于realm类的授权----在数据库中获取,来判断
1、基于ini文件的认证
/*首先安装一个Ini的插件*/
​
shiro的基本语法-----基于ini文件的认证(登录)
​
1、创建工程
​
2、导入下列依赖
    
    1、shiro-core
    2、commons-logging
​
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>
​
3、在resources目录下,创建一个ini文件,用于封装用户信息
​
    #配置用户信息
    [users]
    #用户名=密码
    jack=111
    andy=222
​
4、编写测试类进行测试
​
----------------------------------------------------------------------------------
@@@@@@@在实际应用中,我们不可能将用户名密码写在ini文件中,这样不安全,这些信息都是存放在数据库中的
测视类
package org.java.demo;
​
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.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
​
/**
 * @author arjun
 * @title: iniDemo
 * @description: 描述信息
 * @date 2023.07.12 18:59
 */
​
//基于ini文件的认证
​
public class iniDemo {
​
    public static void main(String[] args) {
​
        //1、获得一个工厂类,用于产生安全管理器securityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
​
        //2、创建安全管理器securityManager
        SecurityManager securityManager = factory.getInstance();
​
        //3、将安全管理器设置到当前运行环境中
        SecurityUtils.setSecurityManager(securityManager);
​
        //4、获得主体subject(代表当前用户),用于执行认证操作
        Subject subject = SecurityUtils.getSubject();
​
        //5、创建令牌token,用于封装用户名及密码
        UsernamePasswordToken token  = new UsernamePasswordToken("jack","111");
​
        try{
            //6、用户登录,如果登录失败将会产生异常
            subject.login(token);
​
            //7、判断用户是否登录
            if(subject.isAuthenticated()){
                //返回true,表示用户已登录
                System.out.println("用户登录成功!");
            }
​
        }catch(UnknownAccountException ex){
            System.out.println("错误:用户名不存在,登录失败");
        }catch (IncorrectCredentialsException ex){
            System.out.println("错误:密码错误,登录失败");
        }
    }
}
2、基于realm类的认证
@@@@@@@基于realm类的认证
​
1、编写AuthcRealm类(领域对象,封装认证、授权的方法)
​
    public class AuthcRealm extends AuthorizingRealm 
​
​
2、重写父类的中两个抽象方法
​
    public class AuthcRealm extends AuthorizingRealm {
​
        //授权的方法
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
        }
​
        //认证的方法
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
           //从令牌中获得用户信息(用户名)
        String principal = (String) token.getPrincipal();
        //根据用户名到数据库中判断,用户名是否存在
        //此处,模拟数据库操作,如果是jack我们就认为当前用户不存在 
        if(principal.equals("jack")){
            return null;//表示用户名不存在
        }
        //用户名存在,从数据库获得当前用户的正确密码
        String pwd = "123";
        
        //创建一个AuthenticationInfo对象,封装认证的用户信息
        /**
         * 参数1:用户信息
         * 参数2:当前用户在数据库对应的密码
         * 参数3:realm类的别名,可以任意指定
         */
        AuthenticationInfo  info = new SimpleAuthenticationInfo(principal,pwd,"myRealm");
        
        return info;
        }
    }
​
3、配置shiro2.ini文件用于配置reaml
​
    [main]
​
    #定义别名,指向Realm
    myRealm=org.java.realms.AuthcRealm
​
    #设置安全管理器采用哪一个Realm类进行认证
    securityManager.realm=$myRealm
​
​
4、编写测试类(测视类同上,只改变引用的文件名--shiro2.ini)
    
   //1、获得一个工厂类,用于产生安全管理器securityManager
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro2.ini");
    ...
3、MD5加密
@@@@@@@@@@@@MD5加密
​
    在实际应用中,一般用户名,密码都是存在数据库中的,对于系统管理员而言,它是可以看到所有用户的用户名,密码
​
    但是这样就非常不安全。为了解决该问题,在开发中,用户名会直接存放到数据库,但密码将会采用MD5加密后,再存放到数据库中
​
    此时,系统管理员看到的密码将会是加密的密码,它并不是真正的密码,并不能直接使用
加密示例
//MD5加密示例类
public class md5Demo {
​
    public static void main(String[] args) {      
        //原始密码
        String pwd="123";
​
        //指定盐,也就是混合在加密算法的最后数据--利用uuid随机生成盐
        String salt = UUID.randomUUID().toString();
        System.out.println("混合参数:"+salt);
​
        //指定加密次数
        int count=new Random().nextInt(10);
        System.out.println("加密次数 :"+count);
​
        //MD5 加密
        Md5Hash md5Hash = new Md5Hash(pwd,salt, count);
        System.out.println("加密后:"+md5Hash.toString());
    }
}
基于realm认证的md5加密
@@@@@@@@@@@基于Realm类进行认证时,采用MD5加密
​
1、在shiro2.ini文件中指定凭证匹配器用于设置加密方式以及加密次数
​
    #指定凭证匹配器(指定加密规则)
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #指定加密方式
    credentialsMatcher.hashAlgorithmName=md5
    #指定散列次数(加密次数)
    credentialsMatcher.hashIterations=3
​
​
2、在shiro2.ini文件中指开realm,并且设置realm采用哪一种凭证匹配器
​
​
    #定义一个变量,指向realm类
    myRealm=org.java.reamls.MyRealm
​
    #指定当前的myRealm类,采用哪一种凭证匹配器,对密码加密
    myRealm.credentialsMatcher=$credentialsMatcher
​
    #指定安全管理器SecurityManager通过哪一个Realm进行认证
    securityManager.realm=$myRealm
        
​
3、在Realm类中认证中的方法中,设置从数据库中查询到的加密后的正确密码以及加密用的盐
​
        /**
         * 参数1:用户信息
         * 参数2:当前用户在数据库对应的密码
         * 参数3:对用户输入的密码加密用的盐
         * 参数4:realm类的别名,可以任意指定
         */
        //设置加密用的盐
        String salt ="accp";
        AuthenticationInfo  info = new SimpleAuthenticationInfo(principal,pwd, ByteSource.Util.bytes(salt),"myRealm");
4、基于ini文件授权
授权:指认证成功后在进行权限、角色判断时,得到用户的角色或者是访问权限
​
1、基于ini文件的授权
    指:将用户的信息、角色、权限写在一个ini文件中
​
    role-----------角色
    authorization--授权
    permission-----权限
    power----------权力
1、编写shiro3.ini文件,在文件中编写如下代码
​
    [users]
    #用户名=密码,角色
    jack=111,role1
    andy=111,role1,role2
    tom=111,role3
    chris=111,role4
​
    [roles]
    #指定角色及权限信息
    role1=user:add,user:query
    role2=user:del,user:update
    role3=user:*
    role4=*:*
​
2、编写测试类进行测试
​
           
 //进行角色判断
            //判断用户是否拥有某一种角色
            if(subject.hasRole("role2")){
                System.out.println("有权限访问.....");
            }else{
                System.out.println("无权限访问....");
            }
​
​
       //判断用户是否拥有某一种访问权限
            if(subject.isPermitted("user:add")){
                System.out.println("有权限访问.....");
            }else{
                System.out.println("无权限访问....");
            }
​
            //判断用户是拥有多种访问权限
            if(subject.isPermittedAll("user:add","user:del","user:query")){
                System.out.println("有权限访问.....");
            }else{
                System.out.println("无权限访问....");
            }

image-20230713123526894

5、基于realm类授权
​
@@@@@@@@@@@@@@@@@@@@@@基于Realm类的权限判断
​
1、编写shiro4.ini文件
​
    [main]
​
    #指定凭证匹配器(指定加密规则)
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #指定加密方式
    credentialsMatcher.hashAlgorithmName=md5
    #指定散列次数(加密次数)
    credentialsMatcher.hashIterations=3
​
​
    #定义一个变量,指向realm类
    myRealm=org.java.realms.AuthcRealm
​
    #指定当前的myRealm类,采用哪一种凭证匹配器,对密码加密
    myRealm.credentialsMatcher=$credentialsMatcher
​
    #指定安全管理器SecurityManager通过哪一个Realm进行认证
    securityManager.realm=$myRealm
​
​
2、修改Realm类授权的方法
​
    @@@@@@@@默认情况下,只有进行权限或者角色判断时,才会执行授权的方法
​
​
      

  //授权的方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
​
        //从PrincipalCollection获得用户信息(也就是认证方法返回的AuthenticationInfo对象中的第一个参数)
        String principal = (String) principals.getPrimaryPrincipal();
​
        //根据用户信息从数据库查询用户的角色或者是访问权限
//        List<String> roles = new ArrayList<>();
//        roles.add("role1");
//        roles.add("role2");
//
//        //创建AuthorizationInfo用于封装用户角色或者访问权限
//        SimpleAuthorizationInfo info  = new SimpleAuthorizationInfo();
//        //指定角色
//        info.addRoles(roles);
​
        //到数据库中查询访问权限
        List<String> list = new ArrayList<>();
        list.add("user:add");
        list.add("user:del");
​
        //创建AuthorizationInfo用于封装用户角色或者访问权限
        SimpleAuthorizationInfo info  = new SimpleAuthorizationInfo();
        //指定访问权限
        info.addStringPermissions(list);
​
        return info;
    }

第二章

shiro综合案例
阶段1:搭建基本结构(与shiro无关)
​
阶段2:加入shrio
​
阶段3:基于shiro的认证(与数据库无关)
​
阶段4:连接数据库进行认证
​
阶段5: 得到访问权限,根据权限加载对应的菜单
​
阶段6:加入缓存,将权限进行缓存
阶段1:基本结构
    1、创建web应用
​
    2、导入依赖(ssm用到依赖)
​
    3、导入log4j.properties,db.properties,mybatis-config.xml
​
    4、编写applicationContext.xml
​
    5、web.xml
​
    6、编写index.jsp
​
    7、编写FirstController
​
    8、编写main.jsp
依赖
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring-version>5.1.6.RELEASE</spring-version>
  </properties>
​
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--    spring相关的依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring-version}</version>
    </dependency>
​
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring-version}</version>
    </dependency>
​
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
​
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.3.1</version>
    </dependency>
​
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>2.1_3</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
​
    <!--        数据源及连接池相关的依赖-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.21</version>
    </dependency>
​
    <!--        web应关的依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.20</version>
    </dependency>
​
<!--    shiro的相关依赖-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.2.6</version>
    </dependency>
  </dependencies>
阶段2:加入shiro
1、加入依赖
1、加入依赖
    
    shiro-core
    shiro-web
    shiro-spring
    shiro-ehcache
​


    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.2.6</version>
    </dependency>
2、编写web.xml
2、编写web.xml文件,配置shiro
​
 
  <!--指定监听器要加载的配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
​
    <!--  配置shiro的过滤器-->
    <filter>
        <filter-name>shiro</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <!--配置属性1,用于指定spring管理shiro的生命周期-->
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
​
        <!-- 配置属性2,用于指定在spring配置文件中注册的shiro过滤器的名称 -->
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>shiroFilter</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiro</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
​
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
​
    <!--配置监听器,加入载所有的配置文件-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
3、shiro配置
3、编写applicationContext-shiro.xml文件,用于进行shiro配置
4、authcrealm连接数据库
4、编写AuthcRealm用于指定认证、授权的方法
​
   
 public class AuthcRealm extends AuthorizingRealm {
​
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
        }
​
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        return null;
        }
    }
5、修改shiro配置
5、修改applicationContext-shiro.xml文件,用于进行shiro配置
​
  
  <!--    注册SHIRO过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--指定要使用的安全管理器-->
        <property name="securityManager" ref="securityManager"/>
        <!--指定如果当前用户未登录,通过哪一个请求地址进入到登录界面-->
        <property name="loginUrl" value="/login.do"/>
        <!--指定shiro过滤品拦截请求的规则-->
        <!--
            /**=anon 它表示所有请求的资源允许匿名访问,不登录也可以访问的
            /**=authc 它表示所有请求的资源必须登录后才能访问
        -->
        <property name="filterChainDefinitions">
            <value>
                /js/**=anon
                /css/**=anon
                /img/**=anon
        /favicon.ico =anon
                /**=authc
            </value>
        </property>
    </bean>
​
    <!--    注册安全管理器securityManager-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="authcRealm"/>
    </bean>
​
    <!--    注册realm-->
    <bean id="authcRealm" class="org.java.reamls.AuthcRealm"/>
6、编写控制器类
6、编写LoginController控制器类
​
    @Controller
    /***
     * 该控制器类只有两种情况下会进入
     * 1 用户未登录时,请求被拦截,会进入.会通过当前类进入到登录界面
     * 2 如果信息错误,登录失败时,也会进入当前控制器类
     * 
     * 如果是正常登录,请求不进入该控制器类的
     */
    public class LoginController {
        
        @RequestMapping("/login")
        public String login(){
        
        //跳转到登录界面
        return "/login";
        }
    }
7、login.jsp
7、编写login.jsp页面,编写登录的表单
    
    注意:用户名必须是:username,密码必须是password
​
        <form action="/login.do" method="post">
        姓名:<input type="text" name="username"/><Br>
        密码:<input type="password" name="password"/><Br>
            <input type="submit" value="登录">
        </form>
8、编写realm类
8、编写reaml类的代码,执行认证
    
    @@@@如果认证成功就会执行之前未执行的请求 
    
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
      
        //获得用户信息
        String principal = (String) token.getPrincipal();
        //到数据库中判断用户名是否存在
        if(principal.equals("jack")){
            return null;
        }
        //得到当前用户的正确密码
        String pwd = "123";
        
        AuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd,"myRealm");
        
        return info;
    }
9、出现错误
@@@@@@@@登录成功后,可以会出现下列错误:
​
    HTTP Status 404 - /favicon.ico  
​
    原因是浏览器找不到图标,解决方案是:
​
​
@@@@@shiro登录成功以后,如果显示favicon.ico错误,原因是:
    
    shiro它会访问一个图标,如果图标无法访问将会导致该错误信息
​
    解决方案:
        1、在shiroFilter中配置,该图标允许匿名访问
            /favicon.ico = anon
        2、在web.xml文件中进行如下配置
            <mime-mapping>
                <extension>ico</extension>
                <mime-type>image/x-icon</mime-type>
            </mime-mapping>

第三章

image-20230714105852862

阶段3:shiro认证
1、在LoginController中编写对应的代码 
        
    @@@@如果未登录,就转向登录界面,如果是登录失败,就抛出异常
​
​
​
    @Controller
    /***
     * 该控制器类只有两种情况下会进入
     * 1 用户未登录时,请求被拦截,会进入.会通过当前类进入到登录界面
     * 2 如果信息错误,登录失败时,也会进入当前控制器类
     *
     * 如果是正常登录,请求不进入该控制器类的
     */
    public class LoginController {
​
        /**
         * 请求只有两种情况进入该控制器
         * 1、未登录
         * 2、登录失败
         * 如果是因为登录失败进入的,请求中request将会携带一个名为shiroLoginFailure的参数,
         * 如果是因为未登录进入的,该参数为null
         * @return
         */
        @RequestMapping("/login")
        public String login(HttpServletRequest request){
​
        //从请求中获得参数shiroLoginFailure,用于判断是未登录进入还是登录失败进入
        String msg = (String) request.getAttribute("shiroLoginFailure");
        System.out.println(msg);
        if(msg!=null){
            //登录失败进入的
            //判断登录失败的原因
            if(msg.endsWith("UnknownAccountException")){
            throw new RuntimeException("用户名不存在!");
            }
            if(msg.endsWith("IncorrectCredentialsException")){
            throw new RuntimeException("密码错误!");
            }
        }
​
        //如果是未登录进入的,就转向跳转到登录界面
        return "/login";
        }
    }
2、编写异常处理类,处理异常
​
​
    @Component
    public class ShiroException implements HandlerExceptionResolver {
        
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
          
        //获得异常原因
        String msg = e.getMessage();
        //获得modelandView
        ModelAndView mv = new ModelAndView("/err");
        //存放异常原因
        mv.addObject("msg",msg);
        return mv;
        }
    }
3、编写异常显示页面err.jsp
​
    <h1>登录失败,原因是:${requestScope.msg}</h1>
​
    <A href="index.jsp">返回</A>
4、编写FirstController的代码。指定登录成功后要执行的操作
​
    @Controller
    public class FirstController {
​
        @RequestMapping("/first")
        public String first(HttpSession session){
​
        //获得登录成功的主体subject
        Subject subject = SecurityUtils.getSubject();
        //从主体中获得认证用户信息(即为Realm类认证方法返回的第一个参数)
        String principal = (String) subject.getPrincipal();
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

![img](https://img-blog.csdnimg.cn/img_convert/b50c0755e5a3c1e5c4bc90f84cf5cf42.png)

![img](https://img-blog.csdnimg.cn/img_convert/cfa17c6f16a6c3f173cd897857f4217f.png)

![img](https://img-blog.csdnimg.cn/img_convert/043982b7eb3917ce4e3a0a01c677f390.png)

![img](https://img-blog.csdnimg.cn/img_convert/d38052b6554e930b8eec70d373020a7e.png)

![img](https://img-blog.csdnimg.cn/img_convert/f202c585231241e83a26fa691d3cbdab.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

``


4、编写FirstController的代码。指定登录成功后要执行的操作

@Controller
public class FirstController {

   @RequestMapping(“/first”)
   public String first(HttpSession session){

//获得登录成功的主体subject
Subject subject = SecurityUtils.getSubject();
//从主体中获得认证用户信息(即为Realm类认证方法返回的第一个参数)
String principal = (String) subject.getPrincipal();

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-h8bgizuZ-1715565752420)]

[外链图片转存中…(img-GjQPAwzh-1715565752420)]

[外链图片转存中…(img-njysricg-1715565752420)]

[外链图片转存中…(img-j3IhEiM9-1715565752421)]

[外链图片转存中…(img-9EFTT13i-1715565752421)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值