10.shiro+springboot

0.项目结构

0.项目功能

让不同权限的用户通过登录进入到一个页面,页面相应的显示不同的模块的功能

1.导入依赖

        <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>
<!--模板-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
<!-- subject用户
securityManager管理所有的用户
Realm 连接数据
-->
<!-- 整合包shiro-spring-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>
<!-- 日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
<!-- 德鲁伊 mysql-->
        <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.2.6</version>
        </dependency>
<!-- mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
<!--  lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
<!--shiro和thymeleaf-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

2.两个配置文件

 application.properties

#绑定mybatis
mybatis.type-aliases-package=com.wu.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
server.port=8081

application.yml

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    #配置德鲁伊,后续可以配置德鲁伊相关的东西
    type: com.alibaba.druid.pool.DruidDataSource
      #SpringBoot默认是不注入这些的,需要自己绑定
    #druid数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

      #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
      #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
    #则导入log4j 依赖就行
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3.数据库

 

 

 4.前端页面

User/add和User/update没什么好说的

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http:www.thymeleaf.org/thymeleaf-extras-shiro">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<!--如果已经登录就不显示登录-->
<div th:if="${session.loginUser}==null"> <a th:href="@{/toLogin}">登录</a></div>
<p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add">
<a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登陆
<p th:text="${msg}" style="color: red;"></p>
<form th:action="@{/login}">
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <p><input type="submit"></p>
</form>
</body>
</html>

5.pojo层

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
    private String perms;
}

6.Mapper层

接口

@Repository
@Mapper
public interface UserMapper {
    User queryUserByName(String name);
}

对应的Mapper.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.wu.mapper.UserMapper">
    <select id="queryUserByName" parameterType="String" resultType="User" >
        select * from mybatis.user where name = #{name}
    </select>
</mapper>

7.Service层

接口

public interface UserService {
    User queryUserByName(String name);
}

实现类

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public User queryUserByName(String name) {
        return userMapper.queryUserByName(name);
    }
}

8.Controller层

@Controller
public class MyController {
    @RequestMapping({"/","/index"})
    public String toIndex(Model model){
        model.addAttribute("msg","hello,Shiro");
        return "index";
    }
    @RequestMapping("/user/add")
    public String add(){
        return "User/add";
    }
    @RequestMapping("/user/update")
    public String update(){
        return "User/update";
    }
    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }
    @RequestMapping("/login")
    public String login(String username,String password,Model model){
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登陆数据
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try {
            subject.login(token);//执行登陆的方法,如果没有异常就ok
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e) {
            model.addAttribute("msg","密码不存在");
            return "login";
        }
    }
    //未授权
    @ResponseBody
    @RequestMapping("/noauth")
    public String unauthorized(){
        return "未经授权无法访问此页面";
    }
}

9.Config配置文件

ShiroConfig

@Configuration
public class ShiroConfig {
    //3.ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager ){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        /*
        anno:无需认证就可以访问
        authc:必须认证了才能访问
        user:必须拥有记住我功能才能用
        perms:拥有对某个资源的权限才能访问
        role:拥有某个角色权限才能访问
         */
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/user/add","perms[user:add]");//有add权限才能访问
        filterMap.put("/user/update","perms[user:update]");
        bean.setFilterChainDefinitionMap(filterMap);
        //设置拦截成功后跳到登陆页面
        bean.setLoginUrl("/toLogin");
        //未授权的页面
        bean.setUnauthorizedUrl("/noauth");
        return bean;
    }
    //2.DefaultWebSecurityManager
    @Bean(name="securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){//绑定下方的类
        DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        webSecurityManager.setRealm(userRealm);
        return webSecurityManager;
    }
    //1.创建realm对象 需要自定义类
    @Bean(name="userRealm")
    public UserRealm userRealm(){
        return new UserRealm();
    }
    //整合shiro和thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

UserRealm自定义类

public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserService userService;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到用户的对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User)subject.getPrincipal();//拿到user对象
        //设置当前用户的权限
        info.addStringPermission(currentUser.getPerms());
        return info;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) authenticationToken;
        //连接真实的数据库
        User user = userService.queryUserByName(usernamePasswordToken.getUsername());
        if(user==null){
            //查无此人
            return null;//自动报没有用户名的异常
        }
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        session.setAttribute("loginUser",user);
        //从这里把认证的用户作为数据传递给授权
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}

测试数据库连接成功的测试类

@SpringBootTest
class DemoApplicationTests {
@Autowired
    UserServiceImpl userService;
    @Test
    void contextLoads() {
        System.out.println(userService.queryUserByName("xixi"));
    }
}

一些spring注解的相关内容

https://blog.csdn.net/u010648555/article/details/76299467?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162442572216780262563579%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162442572216780262563579&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-76299467.pc_search_result_before_js&utm_term=spring%E6%B3%A8%E8%A7%A3&spm=1018.2226.3001.4187

 

 

posted @ 2021-06-23 13:29  一拳超人的逆袭  阅读(80)  评论(0编辑  收藏  举报