SpringBoot整合shiro安全框架

SpringBoot整合Shiro安全框架

①引入依赖

<groupId>com.lp</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-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>
            <scope>runtime</scope>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </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>


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>
        
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

②引入数据源

#配置数据源信息
spring.
	datasource.
		druid.
		driver-class-name:com.mysql.jdbc.Driver
		url:jdbc:mysql://localhost:3306/ceshi?useSSL=false
		username:root
		password:root
#添加打印sql日志信息的配置
logging.
	level.
		com.
			lp.
				dao:debug

③在resource下创建mapper包,里面存放dao的实现类;在templates里面写前端页面
UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lp.dao.UserMapper">

    <select id="selectPermissionByUserId" resultType="java.lang.String">
        select  percode from user_role ur,role_permission rp,permission p where ur.roleid=rp.roleid and rp.perid=p.perid and ur.userid=#{userid}
    </select>
</mapper>

Login.html:登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username"/><br>
    密码:  <input type="text" name="userpwd"/><br>
         <input type="submit" value="登录"/>
        <input type="button" value="注册" onclick="location.href='regist'"/>
</form>
</body>

Success.html:登录成功后跳转的页面

<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录成功 <br>
<shiro:hasPermission name="user:query">
    <a href="/user/query">查询所有用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:update">
    <a href="/user/update">修改用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:delete">
    <a href="/user/delete">删除用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:insert">
    <a href="/user/insert">添加用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:export">
    <a href="/user/export">导出用户</a><br>
</shiro:hasPermission>
</body>
</html>

Unauthorization.html:当该用户没有该权限时跳转的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
该用户没有该权限
</body>
</html>

④创建实体类

//创建用户实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer userid;
    private String username;
    private String userpwd;
    private String sex;
    private String address;
    private String salt;
}

⑤创建dao层

//创建接口继承BaseMapper<?>里面的接口,泛型就写User对象
public interface UserMapper extends BaseMapper<User> {
    /**
     * 根据userid查询User对应的Permission
     * @param userid
     * @return
     */
    List<String> selectPermissionByUserId(Integer userid);
}

⑥创建service层

	public interface UserService {
    /**
     * 根据username查询User信息
     * @param username
     * @return
     */
    User getUserByUserName(String username);

    /**
     * 根据userid查询
     * @param userid
     * @return
     */
    List<String> getPermissionByUserId(Integer userid);
}

⑦实现service接口的实现类

//写我们所需要的业务代码
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public User getUserByUserName(String username) {
        QueryWrapper<User>wrapper = new QueryWrapper<>();
        wrapper.eq("username",username);
        return userMapper.selectOne(wrapper);
    }

    @Override
    public List<String> getPermissionByUserId(Integer userid) {
        return userMapper.selectPermissionByUserId(userid);
    }
}

⑧创建我们自定义的realm类

public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        User principal = (User) principals.getPrimaryPrincipal();
        List<String> permission = userService.getPermissionByUserId(principal.getUserid());
        if (permission.size()>0){
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addStringPermissions(permission);
            return info;
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String s = token.getPrincipal().toString();
        User user = userService.getUserByUserName(s);
        if (user!=null){
            ByteSource salt = ByteSource.Util.bytes(user.getSalt());
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getUserpwd(), salt, this.getName());
            return info;
        }
        return null;
    }
}

⑨创建config包里面写shiro需要的配置

@Configuration
public class ShiroConfig {
    @Bean(value = "securityManager")
    public DefaultWebSecurityManager securityManager(Realm myRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        return securityManager;
    }
    @Bean(value ="myRealm")
    public Realm getRealm(CredentialsMatcher matcher){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(matcher);
        return myRealm;
    }
    @Bean(value ="matcher")
    public CredentialsMatcher getcredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("MD5");
        matcher.setHashIterations(1024);
        return matcher;
    }
    @Bean(value = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        shiroFilterFactoryBean.setSuccessUrl("/success.html");
        HashMap<String, String> map = new HashMap<>();
        map.put("/index.html","anon");
        map.put("/login","anon");
        map.put("/static/**","anon");
        map.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setName("shiroFilter");
        filterRegistrationBean.setFilter(new DelegatingFilterProxy());
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}

⑩创建controller层用于接收和发送请求
PageController:跳转页面经过这里

@Controller
public class PageController {
    @GetMapping("tologin")
    public String tologin(){
        return "login";
    }
}

LoginController:登录提交经过这里

@Controller
public class LoginController {
    @PostMapping("login")
    public String login(String username,String userpwd){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, userpwd);
        try {
            subject.login(token);
            return "success";
        } catch (AuthenticationException e) {
           return "redirect:/tologin";
        }
    }
}

UserController:权限分配经过这里

@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("query")
    @RequiresPermissions("user:query")
    public String query(){
       return "user:query";
    }
    @GetMapping("insert")
    @RequiresPermissions("user:insert")
    public String insert(){
        return "user:insert";
    }
    @GetMapping("delete")
    @RequiresPermissions("user:delete")
    public String delete(){
        return "user:delete";
    }
    @GetMapping("update")
    @RequiresPermissions("user:update")
    public String update(){
        return "user:update";
    }
    @GetMapping("export")
    @RequiresPermissions("user:export")
    public String export(){
        return "user:export";
    }
}

测试:

登陆界面:
在这里插入图片描述
登录成功后的界面:
在这里插入图片描述
用户没有该权限的界面:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值