1.1 Shiro
1.1.1 简介
是一个开源的轻量级的java安全框架,提供身份验证授权,密码管理以及会话管理等功能,相对于security,shiro更加直观易用,提供健壮的安全性。
1.1.2 依赖
需要三个依赖
- shiro-spring-boot-web-starter
这个依赖中包含了web所需要的依赖 - thymeleaf
这个是页面模板的依赖,一般需要使用到 - thymeleaf-extras-shiro
这个是thymeleaf中引入shiro标签的依赖
1.1.3 application中的配置
shiro.enabled=true
开启shiro配置,默认true
shiro.web.enabled=true
开启shiro web配置,默认true
shiro.loginUrl=/login
登录地址,默认就是login.jspshiro.successUrl=/index
登录成功的地址,默认是/
shiro.unauthorizedUrl=/unauthorized
未获得授权默认跳转地址shiro.sessionManager.sessionIdCookieEnabled=true
是否允许URL参数实现会话跟踪,如果网站支持cookie,可以关闭shiro.sessionManager.sessionIdUrlRewritingEnabled=true
允许使用Cookie
1.1.4 在java中配置权限
@Configuration
public class ShiroConfig {
/*
* 这个配置是配置权限用的
* */
@Bean
public Realm realm() {
TextConfigurationRealm realm = new TextConfigurationRealm();
realm.setUserDefinitions("ymy=123,user\n admin=123,admin\n");
// 创建两个账户,ymy对应密码是123,admin对应密码是123.再创建两个权限,
// 其中ymy是user权限,admin是admin权限
realm.setRoleDefinitions("admin=read,write\n user=read");
// 给上面创建的两个权限分配使用限制
// admin权限可以写,user权限只能读
return realm;
}
/*
* 这个配置时配置页面访问用的
* */
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition =
new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/login", "anon");
chainDefinition.addPathDefinition("/doLogin", "anon");
chainDefinition.addPathDefinition("/logout", "logout");
chainDefinition.addPathDefinition("/**", "authc");
/*
* 这里给四种类型的页面赋予权限,首先的登录页面是可以匿名访问,也就是登录是可以在没有
* session的时候就访问的
* 第三种注销是可以访问登录的
* 其他的都是需要认证之后在访问的
* */
return chainDefinition;
}
/*
* 这个配置时为了能够在thymeleaf中使用shiro标签用的
* */
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
其中
- 主要是配置了用户的权限(不使用默认配置,使用自定义配置)
- 然后配置了需要访问的页面(对应以前使用拦截器,就是在未授权的情况下,可以访问登录页面,但是不能访问别的页面)
- 配置的第三个Bean的目的是为了能够在thymeleaf中使用shiro标签
1.1.5 创建用户登录使用的Controller
@Controller
public class UserController {
@PostMapping("/doLogin")
public String doLogin(String username, String password, Model model){
System.out.println("我爱蛋炒饭");
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
System.out.println(username+password);
System.out.println(token);
Subject subject= SecurityUtils.getSubject();
try{
subject.login(token);
/*
* 这里其实是一个登录操作,创建一个subject对象,并使用其中的login方法,传入一个带有用户名密码的对象
* 进行验证,如果验证失败,那么就进入catch,这样就可以向正常的验证失败一样,返回到login页面,并且带有一段登录失败的语句显示在页面上
* */
}catch (AuthenticationException e){
model.addAttribute("error","用户名密码错误,请重新登录");
return "login";
}
return "index";
// 登录成功就重定向到index页面(和失败不同是因为可能主页面需要一些数据)
}
@RequiresRoles("admin")
@GetMapping("/admin")
public String admin(){
return "admin";
}
@RequiresRoles(value = {"admin","user"},logical = Logical.OR)
@GetMapping("/user")
public String user(){
return "user";
}
/*
* 这里给出了两个接口,也就是说,具有具体权限的用户,访问这个接口时才能会有效果
* */
}
对于其他的一些不需要权限的访问,可以直接在webmvc的config中配置
1.1.6 创建一些不需要权限的访问(简介的Controller访问方式)
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/unauthorized").setViewName("unauthorized");
/*
* 这个地方配置了一些过滤器形式的,也就是相当于一个Controller的功能,
* 省了写Controller的麻烦,这样可以直接进行页面的跳转
* */
}
}
1.1.7 创建全局异常处理,(处理一些授权问题)
当遇到一些关于授权方面的无法访问时,可以直接使用这个Controller的返回值
@ControllerAdvice
public class ExceptionController {
/*
* 这个类的目的是创建全局异常处理,也就是处理一些授权异常
* */
@ExceptionHandler(AuthorizationException.class)
public ModelAndView error(AuthorizationException e){
ModelAndView mv=new ModelAndView("unauthorized");
mv.addObject("error",e.getMessage());
return mv;
}
}
当用户访问一些未授权的页面时,跳转到unauthorized页面,并且带着出错异常信息
1.1.8 一些template页面
第一个index.html
Title
Hello ,
注销登录
管理员界面
普通用户页面
第二个login.html
Title
第三个user.html
Title
普通用户页面
第四个admin.html
Title
管理员页面
第五个unauthorized.html
Title
未获授权,非法访问
1.1.9 总结
总结,对于页面访问来说,总的路线是这样的
当客户端请求localhost:8080/doLogin时,页面到login.html,用户输入用户名密码,进入验证阶段,也就进入了PostMapper("/doLogin")的方法中,方法创建了一个Subject对象,并将前台传入的username和password放入UsernamePasswordToken对象中,使用Subject对象的logi方法,传入第二个对象来进行账号密码的验证
验证的时候会根据用户名密码赋予响应的权限
验证成功,就会重定向到index,失败就到login页面,并携带验证失败的信息显示出来。
总的来说,其实和基本的jsp执行方法都是一样的
所以综上所述,基本的shiro就是这么简单,其实用基本的代码也可以实现功能,只是这是一个就像是模板,又像是规范,即可以简化操作,有可以让用户通过这个接口无脑操作从而实现以前写很多代码来实现的功能