Springboot integrated shiro framework

Overview of shiro

  1. Apache Shiro is a security framework for Java
  2. Shiro is a powerful and easy-to-use Java security framework, mainly used for more convenient authentication, authorization, encryption, session management, integration with the Web, caching, etc.
  3. Shiro is small and simple to use
  4. There is spring security in spring, which is a permissions framework. It depends too closely on spring and is not easy to use without shiro.
  5. shiro does not depend on spring, shiro can not only implement permission management for web applications, but also implement c / s system, distributed system permission management,
  6. Shiro is a lightweight framework, and more and more enterprise projects are using Shiro.

Shiro core concepts

Insert picture description here

  1. Authentication: Identity authentication / login to verify whether the user has the corresponding identity;
  2. Authorization: Authorization, that is, authorization verification, to verify whether an authenticated user has a certain authorization;
  3. Session Manager: Session management, that is, a session after a user logs in. Before logging out, all its information is in the session;
  4. Cryptography: encryption to protect the security of data
  5. Web Support: Web support, can be easily integrated into the Web environment;
  6. Caching: Caching, for example, after a user logs in, their user information and roles / permissions do not have to be checked every time, which can improve efficiency;
  7. Concurrency: Shiro supports concurrent verification of multi-threaded applications, that is, if another thread is started in one thread, the permissions can be automatically propagated;
  8. Testing: Provide testing support;
  9. Run As: Allow one user to pretend to be another user (if they allow) to access;
  10. Remember Me: Remember me, this is a very common function, that is, after logging in once, you don't need to log in if you come back next time.

Main concepts

1. Subject current user

  1. It can be something that human crawlers currently interact with the software
  2. In shiro, we can collectively refer to "users" anywhere in the code, you can easily get Shiro Subject.
  3. Once you get the Subject, you can immediately get 90% of what you want to do with Shiro for the current user, log in, log out, access the session, perform authorization checks, etc.

2. SecurityManager

  1. SecurityManager manages the security operations of all users
  2. Reference to multiple internal nested security components, which is the core of the Shiro framework
  3. You can think of it as the DispatcherServlet front controller.
  4. Used to schedule various Shiro framework services

3. Realms

  1. Realms is the user's information authenticator and the user's authority authenticator
  2. When performing authentication (login) and authorization (access control), Shiro will find a lot of content from the Realm of the application configuration
  3. Realm can be understood as a DAO that reads user information, roles and permissions
  4. SecurityManager wants to verify the user's identity and permissions, then it needs to obtain the corresponding information from Realm for comparison to determine whether the user's identity is legal
  5. Realm can be regarded as a DataSource, that is, a secure data source.

4. Shiro architecture

Insert picture description here

  1. subject: The subject can be a user or a program. To access the system, the system needs to authenticate and authorize the subject.
  2. authenticator: The authenticator body performs authentication finally through the authenticator.
  3. authorizer: Authorization of the main body of the authorizer is finally carried out through the authenticator.
  4. sessionManager: Session management web applications generally use web containers to manage sessions. Shiro also provides a set of session management methods.
  5. sessionDao: manage session data through sessionDao,
  6. cacheManager: The cache manager mainly caches session and authorization data, such as managing the authorization data through cacheManager and integrating with ehcache to manage the cached data.
  7. realm: The realm is equivalent to a data source, and access to authentication and authorization related data through realm.
  8. cryptography: Password management provides a set of encryption / decryption components for easy development. For example, provide commonly used hash, encryption / decryption and other functions.

Springboot matching shiro

  1. Create a new springboot project
    Insert picture description here

  2. Import springboot-web dependenciesInsert picture description here

  3. To write controller and front-end login page, you
    need to integrate thymeleaf to join thymeleaf's dependencies

 <!--thymeleaf依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>

Insert picture description here
4. Write the front-end page
Write login.html, add.html, delete.html, index.html in the templates directory to
import dtd of thymeleaf

xmlns:th="http://www.thymeleaf.org"

login.html
Insert picture description here

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form th:action="login">
    <input type="text" name="username" value="">
    <input type="password" name="password" value="">
    <input type="submit" value="登录">
</form>
</body>
</html>

index.html
Insert picture description here
add.html
Insert picture description here
delete.html
Insert picture description here
5. Write a controller to jump to the login page
Insert picture description here

@RequestMapping({"/","tologin"})
    public String tologin(){
        return "login";
    }
  1. Run the startup browser and enter localhost: 8080
    Insert picture description here
  2. Import springboot to integrate shiro and mybatis to connect to the database
    Insert picture description here
		<!--shiro-整合spring的包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.2</version>
        </dependency>
          <!--shiro整合thymeleaf-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
         <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
  1. Create a database for the next authentication and authorization
    Insert picture description here
    Insert picture description here
##配置数据驱动信息  (key固定)
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql:///spring_shiro
spring.datasource.username = root
spring.datasource.password =123456

Add database information in application.properties
Insert picture description here

  1. Write mapper, service, pojo
    pojo:
    Insert picture description here
    mapper:
    Insert picture description here
    service:
    Insert picture description here
    Impl:
    Insert picture description here
    controller: test whether it can be queried
    Insert picture description here
    Insert picture description here
  2. Write shiroconfig configuration class
    Insert picture description here
  3. Write realm class to inherit AuthorizingRealm class and implement methods
    Insert picture description here
  4. Write code in shiroConfig
    Insert picture description here
@Configuration
public class shiroConfig {

    //3. shiroFilterfactaryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);//设置安全管理器
        shiroFilterFactoryBean.setLoginUrl("/toLogin");//没有认证后跳到的页面
        /**
         * shiro的内置过滤器
         anon:无需认证就可以访问 默认
         authc:必须认证了才能访问
         user:必须拥有记住我功能才能访问
         perms:必须拥有对某个的权限才能访问
         role:拥有某个角色权限才能访问
         */
        //添加shiro的内置过滤器  设置要拦截的url
        Map<String,String>  filterChainDefinitionMap=new LinkedHashMap<>();//拦截
        filterChainDefinitionMap.put("/add","authc");// /add请求必须认证才能访问
        filterChainDefinitionMap.put("/del","authc");//del必须认证才能访问
        // filterChainDefinitionMap.put("user/**","authc");//支持通配符
        //授权
        filterChainDefinitionMap.put("/add","perms[user:add]");//没有这个user:add权限的会被拦截下来
        filterChainDefinitionMap.put("/del","perms[user:delete]");//没有这个user:delete权限的会被拦截下来
        //未授权的跳转的url
        shiroFilterFactoryBean.setUnauthorizedUrl("/Unauthorized");
        //设置注销的url
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//把设置好的过滤设置到ShiroFilterFactoryBean
        return shiroFilterFactoryBean;
    }

    //2. DefaultWebSecurityManager
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm对象  userRealm
        securityManager.setRealm(userRealm);
        return  securityManager;
    }
    //1. 创建realm对象 自定义的·类
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //整合shiroDialect:用来整合shiro-thymeleaf
    @Bean
    public ShiroDialect getshiroDialect(){
        return new  ShiroDialect();
    }

}
  1. Write code in UserRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    InfoService service;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权 doGetAuthorizationInfo");
        SimpleAuthorizationInfo simpInfo = new SimpleAuthorizationInfo();
        //获取当前用户的对象
        Subject subject=SecurityUtils.getSubject();
        Info user = (Info)subject.getPrincipal();//获取用户信息
        simpInfo.addStringPermission(user.getPerm());//获取数据库权限
        return simpInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证 doGetAuthorizationInfo");
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken userToken=(UsernamePasswordToken)authenticationToken;//获取登录的信息
        //获取用户名 密码  数据库取
        System.out.println(userToken.getUsername());
        Info query = service.queryByName(userToken.getUsername());
        System.out.println(query);
        if(query==null){//没有这个用户
            return null;
        }
        Session session=subject.getSession();//获取用户的session
        session.setAttribute("loginuser",query);

        if(!userToken.getUsername().equals(query.getUsername())){//判断登录的用户名密码 匹配数据库是否正确
            return null;//抛出异常
        }
        //密码认证,shiro做
        return new SimpleAuthenticationInfo(query,query.getPassword(),"");
    }
}

Insert picture description here
14. Rewrite the controller
Insert picture description here

    @RequestMapping("/login")
    public String login(String username,String password){
        try {
            //获取当前的用户
            Subject subject = SecurityUtils.getSubject();
            //封装用户的登录数据
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
            subject.login(usernamePasswordToken);//执行登录的方法 没有异常就成功了
            return "index";
        } catch (UnknownAccountException e) {
            /**
             * 异常信息
             * UnknownAccountException :用户名不存在
             * IncorrectCredentialsException:密码错误
             */
            e.printStackTrace();
            System.out.println("用户名不存在");
        }catch (IncorrectCredentialsException e){
            System.out.println("密码错误");
        }
        return "login";
    }

    @RequestMapping("/add")
    public String add(){//跳转页面
        return "add";
    }
    @RequestMapping("/del")
    public String delete(){//跳转页面
        return "delete";
    }
     @RequestMapping("/Unauthorized")
    public String Unauthorized(){//没有权限跳转的url
        return "Unauthorized";
    }
    //注销
    @RequestMapping("/logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        session.setAttribute("loginuser",null);//清空session
        return "login";
    }
  1. Write an unauthorized page
    Unauthorized.html
    Insert picture description here
  2. run:
    Insert picture description here

Insert picture description here
The root user only has user: delete permissions, so you can only see the delete button. The
Insert picture description here
Insert picture description here
dj user has only user: add permissions, and you can only see the
Insert picture description here
Insert picture description here
ss user.

There are also encryption methods such as md5, which can be added by yourself and will not be introduced one by one.

Focus: shiroConfig class and UserRealm class configure the core **

Guess you like

Origin www.cnblogs.com/joker-dj/p/12690648.html