shiro验证【springboot mybatis个人博客系统(二)】

时间:2022-12-20 10:35:13

上一篇博客完成了业务模型层,这一篇完成控制层和视图层,结合shiro安全认证框架,实现登录验证。这样正好可以体现MVC模式。
本项目的GitHub地址https://github.com/shinyjunjun/myblog

1、shiro

我也是看别人的博客,学习使用这个框架,shiro的相关博客,稍微花点时间去学习一下,还是很好使用的,关键是要理解流程和思想。任何人都可以浏览博客,不需要任何的认证,但是要管理网页的时候,需要验证,即验证是否为博主,只有认证通过时,才可以进入管理网页的界面。
添加依赖如下:

        <!-- Apache shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.5</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.5</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.5</version>
</dependency>

2、MyRealm

在realm包中建立此类,用来获取封装正确的信息交给shiro

public class MyRealm extends AuthorizingRealm {

@Autowired
@Qualifier("bloggerService")
private BloggerService bloggerService;

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 不需要角色和权限验证,只有自己为博主
return null;
}

/*
* 对当前登录的用户进行身份认证
*/

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();// 根据刚刚传过来的token获取用户名
Blogger blogger = bloggerService.findByUsername(username);//只是根据用户名查询出,不涉及密码
if (blogger != null) {
System.out.println("验证信息:"+ blogger);
// 把获取到的用户存到session中
SecurityUtils.getSubject().getSession().setAttribute("blogger", blogger);
// 把从数据库中查询出来的博主信息放到AuthenticationInfo中,即把正确的用户名,密码,交给shiro,再和前台输入的校验。
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(blogger.getUsername(),
blogger.getPassword(), "MyRealm");
return authenticationInfo;
} else {
return null;
}

}

}

3、ShiroConfig

在config包中,添加shiro的配置类

@Configuration
public class ShiroConfig {

/**
* shiroFilter
* @param manager
* @return
*/

@Bean(name="shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
// 配置登录的url
bean.setLoginUrl("/login");
//bean.setSuccessUrl("/admin/main");
// 过滤链
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon"); // 表示可以匿名访问
filterChainDefinitionMap.put("/admin/**", "authc");// 管理员权限需要验证过滤

bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}

/**
* 注册自定义的Realm
* @return
*/

@Bean(name="myRealm")
public MyRealm myRealm() {
MyRealm myRealm=new MyRealm();
return myRealm;
}

/**
* 声明SecurityManager
* @param myRealm
* @return
*/

@Bean(name="securityManager")
public SecurityManager securityManager(@Qualifier("myRealm") MyRealm myRealm) {
System.err.println("加载shiro");
DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
manager.setRealm(myRealm);
return manager;
}


/**
* 保证实现了shiro内部lifecycle函数的bean执行
* @return
*/

@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}


/**
* 开启shiro,首先创建代理
* @return
*/

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}

/**
* 再加载securityManager
* @param manager
* @return
*/

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(manager);
return advisor;
}


}

4、控制层Controller

4.1、BloggerController

在controller包下,建立BloggerController

@Controller
@RequestMapping("/blogger")
public class BloggerController {

@Autowired
@Qualifier("bloggerService")
private BloggerService bloggerService;

@RequestMapping("/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password,
Model model,RedirectAttributes redirectAttributes) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);// 会交给MyRealm中的doGetAuthenticationInfo方法去验证
redirectAttributes.addFlashAttribute("username",username);
return "redirect:/admin/main";//重定向到此路径,进入后台管理系统。
} catch (AuthenticationException e) {
e.printStackTrace();
model.addAttribute("message", "用户名或密码错误");
return "login";//返回登录视图
}
}
}

4.2、BloggerAdminController

在controller.admin包下,建立BloggerAdminController,这是管理博主信息的控制器,现在暂时没有需要添加的方法。

/**
* 管理博主的控制器
* @author jun
*
*/

@Controller
public class BloggerAdminController {

}

5、MyWebMvcConfig

在config包中,建立MyWebMvcConfig类,用来添加自定义的MVC的相关配置,最方便的就是添加只负责跳转到视图的控制器。

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter{

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("index");//首页
registry.addViewController("/login").setViewName("login");//登录页面
registry.addViewController("/admin/main").setViewName("admin/main");//后台管理的主页
}
}

6、视图层View

因为springboot帮助我们配好了ViewResolver,我们只需要在templates文件夹下,建立视图即可,推荐使用tymeleaf代替jsp。这里只给出login.html代码

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="fragment::header"/>
<title>用户登录页面</title>

<body>

<div class="col-md-6 col-md-offset-3" style="margin-top:50px;height:50px;">
<h4 class="text-danger" th:text="${message}" style="text-align: center;">用户名或密码错误</h4>
</div>

<form id="login" class="form-horizontal" role="form" th:action="@{/blogger/login}" th:method="POST">
<div class="form-group">
<label for="username" class="col-md-5 control-label">用户名:</label>
<div class="col-md-2">
<input class="form-control" type="text" id="username" name="username" placeholder="请输入用户名" />
</div>
</div>

<div class="form-group">
<label for="password" class="col-md-5 control-label">密&nbsp;&nbsp;&nbsp;码:</label>
<div class="col-md-2">
<input class="form-control" type="password" id="password" name="password" placeholder="请输入密码"/>
</div>
</div>

<div class="col-md-offset-5 col-md-2">
<input type="submit" value="登录" class="btn btn-primary btn-block" />
</div>
</form>

</body>
</html>

这里需要注意的是

th:action="@{/blogger/login}"

提交到控制器处理

7、结果展示

首先启动项目,进入http://127.0.0.1:8080/druid/index.html监控网页

7.1、/admin/main

未登录直接输入地址localhost:8080/admin/main,会被重定向到login
shiro验证【springboot mybatis个人博客系统(二)】

7.2、/login

输入了错误的用户名之后,会返回,需要继续验证
shiro验证【springboot mybatis个人博客系统(二)】
登录成功
shiro验证【springboot mybatis个人博客系统(二)】

7.3、/index

输入地址localhost:8080/index
不需要任何验证,即可进入博客首页,这里只是显示首页,具体的功能以后实现。
shiro验证【springboot mybatis个人博客系统(二)】

7.4 druid监控URI

shiro验证【springboot mybatis个人博客系统(二)】
没毛病,还可以自己查看SQL结果。

8、总结

项目的MVC结构以及全部搭建完成,目前使用了druid,shiro,以后需要什么功能再慢慢添加。没什么大问题,就是理解模式。
GitHub地址