Springbooot整合shiro框架进行认证授权-----小白篇

环境搭建

首先我是基于Springboot整合shiro框架进行的。然后用Mybatis进行的数据库连接操作;

准备工作
喜闻乐见的导包:
	<dependencies>
	
		<!--Springboot组件-->
		<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>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.22</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>
		
		<!--日志-->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		
		<!--lombok组件-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		

		<!--shiro
		Subject 用户
		SecurityManager 权限管理
		Reolam 连接数据
		-->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.1</version>
		</dependency>

		<!--导入模板引擎-->
		<dependency>
			<groupId>com.github.theborakompanioni</groupId>
			<artifactId>thymeleaf-extras-shiro</artifactId>
			<version>2.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

	</dependencies>
设置配置文件

application.yml

##数据库连接
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&useUnicode=true&charaching=utf-8
    type: com.alibaba.druid.pool.DruidDataSource
    dbcp2:
      initial-size: 5
      min-idle: 5
      max-wait-millis: 600000
      max-total: 20
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 30000
      validation-query: SELECT 1 FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true

##数据库扫描
mybatis:
  type-aliases-package: com.awei.springboot_shiro.pojo
  mapper-locations: classpath:mybatis/*.xml
数据库

数据库名: mydb
然后创建一张表叫做: user
字段就简单的设置一些:在这里插入图片描述
给些数据

连接数据库

在这里插入图片描述
这是项目目录,很简单得一个Demo;
连接数据库就不多赘述了

mapper接口

@Mapper
@Repository
public interface usermapper {

     User querUserByUsername(String  username);
     
}

mapper.xml

<mapper namespace="com.awei.springboot_shiro.mapper.usermapper">

    <select id="querUserByUsername" parameterType="String" resultType="user">
        select * from user where username = #{username}
    </select>

</mapper>

userservice

public interface userservice {

    public User querUserByUsername(String username);
}

userServiceImpl

@Service
public class userServiceImpl implements userservice {

    @Autowired
    usermapper usermapper;

    @Override
    public User querUserByUsername(String username) {
        User user = usermapper.querUserByUsername(username);
        return user;
    }
}

User

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer userId;
    private String username;
    private String password;
    private String perms;
}

前端界面(非常丑,测试用)
index.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:shiro="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>

<p th:text="${msg}" style="color: red"></p>

<div th:if="${session.loginUser}==null">
<a th:href="@{/tologin}">登录</a>
</div>

<div th:if="${session.loginUser}!=null">
    <a th:href="@{/logout}">退出登录</a><br>
</div>

<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>

<form th:action="@{/login}" method="post">
    <P>用户名:<input type="text" name="username"></P>
    <P>密码:<input type="text" name="password"></P>
    <p><input type="submit"></p>
</form>

</body>
</html>

user文件夹下得add.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
this is add html
</body>
</html>

update.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
this is update html
</body>
</html>
关键点来了~~

首先是导入了shiro依赖后关键是
config
Realm

shiroConfig:

@Configuration
public class shiroconfig {

    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);
        /**
         * anon :无需认证直接访问
         * authc:必须认证了才能访问
         * user:必须remmeber me 才能访问
         * perms:必须拥有某个权限才能访问
         * role:必须拥有某个角色才能访问
         */
        //拦截
        HashMap<String,String> map = new HashMap<>();

        //权限操作
        map.put("/user/add","perms[user:add]");
        map.put("/logout","logout");
        map.put("/user/update","perms[user:update]");
        map.put("/user/*","authc");
        bean.setFilterChainDefinitionMap(map);

        //设置跳转登录界面
        bean.setLoginUrl("/tologin");
        //设置未授权请求
        bean.setUnauthorizedUrl("/noauth");
        return  bean;
    }
    
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager =  new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);
        return  defaultWebSecurityManager;
    }
    
    @Bean
    public UserRealm userRealm(){
        return userRealm;
    }
    //整合模板引擎
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

从下往上看就容易一些,模板引擎只是在这里申明一下要用,从userRealm()开始看
这里边就把是否登录了? 还有登录这个人有啥子角色权限?这些信息存住,然后丢给
上边得DefaultWebSecurityManager()方法让他去执行判断,放行还是拦住。然后
这个Manager就去到了ShiroFilterFactoryBean()拦截器这边,这里卡死所有访问
路径,然后让Manager来看是不是要放行或者拦住;通过存住得数据和拦截规则进行匹配

然后上边需要一个Realm;从哪儿来,写呗
UserRealm:

public class UserRealm extends AuthorizingRealm{
    @Autowired
    userservice userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //需要拿到用户信息并且将权限赋予用户
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();

        String perms = currentUser.getPerms();
        //查询出来用户具有多个权限赋予
        Set<String> set=new HashSet<>();
        String[] split = perms.split(",");
        Arrays.stream(split).forEach(perm ->set.add(perm));

        info.setStringPermissions(set);
        return info;
    }
    
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken Token) throws AuthenticationException {
        //连接数据库
        UsernamePasswordToken token = (UsernamePasswordToken)Token;
        User user = userService.querUserByUsername(token.getUsername());
        if(user == null){
            return  null;
        }

        //Subject 获取用户信息
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        //放入session然后控制前端显示对应按钮
        session.setAttribute("loginUser",user);
        

        //自动获取密码
        //MD5 加模  MD5盐值加密  MD5不可逆
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        return info;
    }
}

好的这里就是上边得config需要得realm了 这个又重要了,首先看到
继承至AuthorizingRealm重写得两个长得贼像得方法
doGetAuthorizationInfo():授权
doGetAuthenticationInfo():认证
认证说白了就是登录告诉他 他帮你判断是啥子问题
例如:没有用户,账号错误,密码错误。。。
认证完了,说明有这么个人,但是授权就是通过你这个人去数据库
找到他有啥子角色啊 权限啊,弄出来告诉这个realm。他就完全了
就可以进行config里边得判断操作了。
一饮一琢,前因后果;

最后还有一个

@Controller
public class mycontroller {

    @RequestMapping({"/","/index"})
    public String toindex(Model model){
        model.addAttribute("msg","shiro is success");
        return  "index";
    }

    @RequestMapping("/user/add")
    public String toadd(){
        return  "/user/add";
    }

    @RequestMapping("/user/update")
    public String toupdate(){
        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);
            model.addAttribute("msg","登录成功");
            return "/index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg","用户名错误");
            return  "/index";
        }catch (IncorrectCredentialsException e) {
            model.addAttribute("msg","密码错误");
            return  "/index";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "未经授权,无法访问";
    }
}

这里就只有这个登录看着有点绕,总而言之subject,把登录得参数弄给他就好了;
他能带着这些东西到处跑。

总而言之,就是简单,直接照搬,数据库也弄一样得,随意操作。其实密码需要加密处理,不能明文操作得,无所谓了。小白篇,自娱自乐用,不要当真~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值