Apache shiro例子

apache shiro例子

閒來無事看到之前寫的shiro例子,傳上來,

之前在一家公司接觸過一個項目用到了shiro,不過那個項目是公司買來的,前後端封裝的比較厲害,用着不是並那麼方便,簡單學習shiro後,寫了個小demo。
shiro相比spring的安全框架上手要友好的多。

這是基本結構。
在這裏插入圖片描述
我使用的是spring boot ,這樣方便配置,簡單的寫了個登陸過程。採用spring的thymeleaf。spring data jpa讀取數據庫中用戶信息作權限判斷
啓動類就不貼了,會spring boot的都沒問題

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 http://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.1.4.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>org.zhengyj</groupId>
   <artifactId>springboot-shiro</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>springboot-shiro</name>
   <description>Demo project for Spring Boot</description>

   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-jpa</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-thymeleaf</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.47</version>
       </dependency>
       <dependency>
           <groupId>org.apache.shiro</groupId>
           <artifactId>shiro-spring</artifactId>
           <version>1.3.2</version>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.1.6</version>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
   </dependencies>

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

</project>

application.yml
server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot_shiro?useUnicode=true&amp;characterEncoding=UTF-8&useSSL=true
    username: root
    password: root123
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
  http:
    encoding:
      charset: utf-8
      enabled: true
  thymeleaf:
    prefix: classpath:/templates/
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>登錄頁面</title>
</head>
<body>
<form action="/loginsave">
    用戶名:<input name="name" type="text"/><br>
    密碼:<input name="password" type="text"/><br>
    <input type="submit" value="登錄系統"/>
</form>
<p th:text="${hello}"></p>
</body>
</html>
controller
package org.zhengyj.springbootshiro.controller;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.zhengyj.springbootshiro.entity.User;
import org.zhengyj.springbootshiro.service.LoginService;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;

/**
 *
 * @Author zhengyj
 * @Description :登錄控制層
 * @Date 2019/4/17
 **/

@Controller
public class LoginController {


    /**
     * 首頁
     * @return
     */
    @RequestMapping(value = "/index")
    public String index(){
        return "index";
    }
    /**
     * 登錄
     * @return
     */
    @RequestMapping(value = "/login")
    public String login(){
        return "login";
    }
	/**
	* 此處做權限跳轉處理,返回不同頁面
	*/
    @RequestMapping(value = "/loginsave")
    public String loginSave(User user){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(),user.getPassword());
        try{
            subject.login(token);
            //這個index頁面就是隨便寫點什麼標註下就行
            return "index";
        }catch(UnknownAccountException e){
            return "login";
        }catch(IncorrectCredentialsException i){
            return "login";
        }
    }

}
User類(這個可以用lombok,有點懶了)
package org.zhengyj.springbootshiro.entity;
import javax.persistence.*;
import java.util.List;

/**
     *
     * @Author zhengyingjun
     * @Description :shiro 用戶類
     * @Date 2019/4/17
     **/
    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;

        @Column(unique = true)
        private String name;

        private String password;
        @OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
        private List<Role> roles;

        public List<Role> getRoles() {
            return roles;
        }

        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
}

Role
package org.zhengyj.springbootshiro.entity;

import javax.persistence.*;
import java.util.List;

/**
 *
 * @Author zhengyingjun
 * @Description :shiro 角色類
 * @Date 2019/4/17
 **/

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String roleName;
    @ManyToOne(fetch = FetchType.EAGER)
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<Permission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<Permission> permissions) {
        this.permissions = permissions;
    }

    @OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
    private List<Permission> permissions;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}
Permission
package org.zhengyj.springbootshiro.entity;

import javax.persistence.*;

/**
 *
 * @Author zhengyingjun
 * @Description : shiro 權限類
 * @Date 2019/4/17
 **/
@Entity
public class Permission {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String permission;

    @ManyToOne(fetch = FetchType.EAGER)
    private Role role;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}
RoleRepository(使用的Spring Data JPA)
package org.zhengyj.springbootshiro.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.zhengyj.springbootshiro.entity.Role;
/**
 *
 * @Author zhengyingjun
 * @Description :角色
 * @Date 2019/4/17
 **/

public interface RoleRepository extends JpaRepository<Role,Long> {
}
UserRepository
package org.zhengyj.springbootshiro.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.zhengyj.springbootshiro.entity.User;
/**
 *
 * @Author zhengyingjun
 * @Description :用戶
 * @Date 2019/4/17
 **/
public interface UserRepository extends JpaRepository<User,Long> {
    /**
     *自定義查詢
     * @param name
     * @return
     */
    User findByName(String name);
}
service接口(有些好像是沒用上)
package org.zhengyj.springbootshiro.service;
import org.zhengyj.springbootshiro.entity.Role;
import org.zhengyj.springbootshiro.entity.User;
/**
 *
 * @Author zhengyingjun
 * @Description :業務
 * @Date 2019/4/17
 **/

public interface LoginService {

    User addUser(User user);

    Role addRole(User user,String rolename);

    User findByName(String name);
}
service實現類
package org.zhengyj.springbootshiro.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zhengyj.springbootshiro.entity.Permission;
import org.zhengyj.springbootshiro.entity.Role;
import org.zhengyj.springbootshiro.entity.User;
import org.zhengyj.springbootshiro.repository.RoleRepository;
import org.zhengyj.springbootshiro.repository.UserRepository;
import org.zhengyj.springbootshiro.service.LoginService;
import java.util.ArrayList;
import java.util.List;
/**
 *
 * @Author zhengyingjun
 * @Description :具體實現
 * @Date 2019/4/17
 **/

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Override
    public User addUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public Role addRole(User user,String rolename) {
        Role role = new Role();
        role.setRoleName(rolename);
        role.setUser(user);
        Permission permission1 = new Permission();
        permission1.setPermission("create");
        permission1.setRole(role);
        Permission permission2 = new Permission();
        permission2.setPermission("update");
        permission2.setRole(role);
        List<Permission> list = new ArrayList<>();
        list.add(permission1);
        list.add(permission2);
        //放入role統一保存
        role.setPermissions(list);
        roleRepository.save(role);
        return role;
    }
    @Override
    public User findByName(String name) {
        return userRepository.findByName(name);
    }
}

接下來就是最重要的配置了
這個簡要說明下,用到哪個頁面就配置哪個

package org.zhengyj.springbootshiro.config;
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 zhengyingjun
 * @Description :shiro 過濾配置
 * @Date 2019/4/17
 **/
@Configuration
public class ShiroConfiguration {
    /**
     * 加入註解
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name = "myShiroRealm")
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    /**
     * 權限管理
     * @return
     */
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<>();
        //登錄
        shiroFilterFactoryBean.setLoginUrl("/login");
        //首頁
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //報錯頁
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        //退出
        map.put("/logout","logout");
        map.put("/login","anon");
        map.put("/loginsave","anon");
        //對所有用戶認證
        map.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }
}

認證與校驗

package org.zhengyj.springbootshiro.config;
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;
import org.zhengyj.springbootshiro.entity.Permission;
import org.zhengyj.springbootshiro.entity.Role;
import org.zhengyj.springbootshiro.entity.User;
import org.zhengyj.springbootshiro.service.LoginService;

@Slf4j
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private LoginService service;
    /**
     * 添加權限
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("授權");
        User user = (User) principalCollection.getPrimaryPrincipal();
        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 {
        log.info("認證");
        //??先進行認證?
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
       String name = (String)authenticationToken.getPrincipal();
        User user = service.findByName(name);
        //空值校驗
        if (user == null) {
            return null;
        } else {
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user.getName(), user.getPassword(), getName());
            return simpleAuthenticationInfo;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章