JavaWeb|Springboot整合Shiro实现登录验证

简介: JavaWeb|Springboot整合Shiro实现登录验证

1 关于Shiro

Apache Shiro 是一个Java的安全框架,主要有三个核心的组件:

Subject:指当前的操作用户。

SecurityManager:安全管理器,Shiro通过它来管理内部组件。

Realm:用于权限的验证,需要自己实现。


2 步骤

首先引入Shiromaven

<!--整合shiro-->
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring-boot-web-starter</artifactId>
   <version>1.4.0</version>
</dependency>

application.properties里添加Shrio的配置信息:

#1.第一行表示是否允许将sessionld 放到cookie 
shiro.sessionManager.sessionIdCookieEnabled=true
#2第二行表示是否允许将sessionld 放到Url地址拦中
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
#3.第三行表示访问未获授权的页面时,默认的跳转路径
shiro.unauthorizedUrl=/login
#4.第四行表示开启shiro
shiro.web.enabled=true
#5.第五行表示登录成功的跳转页面
shiro.successUrl=/index
#6.第六行表示登录页面
shiro.loginUrl=/doLogin

需要实现一个Realme类,继承AuthorizingRealm,并实现它的方法,其中一个是AuthorizationInfo,需要自己写对于权限的管理,另一个是AuthenticationInfo,这里是写登录验证。具体代码如下:

public class UserRealm extends AuthorizingRealm {
   @Autowired
   private StudentServiceImpl studentService;

    @Override
   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
       return null;
    }
   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = authenticationToken.getPrincipal().toString();
        Optional<Student> studentOptional = studentService.findStudentBySno(username);
       if (studentOptional.isPresent()) {
            Student student = studentOptional.get();
           return new SimpleAuthenticationInfo(username, student.getPassword(), ByteSource.Util.bytes(username), getName());
}
       throw new UnknownAccountException("不存在");
    }
}

登录验证是先获取到username,然后查到该用户的相关信息,如果不存在则返回一个UnknownAccountException异常。存在则返回一个SimpleAuthenticationInfo,参数是username、数据库查到的密码、还有盐值和用户名。接着需要配置Shiro

@Configuration
public class ShiroConfig {
   @Bean
   UserRealm userRealm() {
       return new UserRealm();
    }
   @Bean
   DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm());
       return defaultWebSecurityManager;
    }
   @Bean
   ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition defaultShiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
        defaultShiroFilterChainDefinition.addPathDefinition("/doLogin""anon");
        defaultShiroFilterChainDefinition.addPathDefinition("/**""authc");
       return defaultShiroFilterChainDefinition;
    }
}

 

将刚刚的UserReaml交给SecurityManager进行管理。并且设置过滤器,比如哪些接口是需要登录后或者某种权限才能访问的。其中 anon 表示匿名即游客就能访问,这里设置了登录接口。authc是需要登录验证后才能访问。除了这两种还有其他:

authcBasiclogoutnoSessionCreationpermsportrestrolesssluser

如果用户开启了RememberMe,则当用户关闭浏览器,下次访问时,不再是authc,而是user。因为authc是需要重新认证的。User就表示该用户曾经被Shiro记住过。

接下来写LoginController

@PostMapping("/doLogin")
public Result<Object> doLogin(@RequestBody UserToken userToken) {
    Subject subject = SecurityUtils.getSubject();
    String pwd = ShiroKit.mds(String.valueOf(userToken.getPassword()), userToken.getUsername());
    UsernamePasswordToken token = new UsernamePasswordToken(userToken.getUsername(), pwd);
    String sessionId = (String) subject.getSession().getId();
   try {
        subject.login(token);
        Map<String, String> map = new HashMap<String, String>();
        map.put("sessionId", sessionId);
        map.put("username", userToken.getUsername());
       return common.SUCCESS(map);
    } catch (Exception e) {
       return common.ERROR(codeEnum.getERR_PWD(), "用户名或密码错误""");
    }
}

因为密码不是明文储存在数据库中的,所以这里采用了MD5加密,没有使用Shiro的加密方式。需要将获取到的密码进行再次加密后和数据库进行比对验证。

加密方式:

public class ShiroKit {
   public static String mds(String password, String salt) {
       return new Md5Hash(password, salt, 1).toHex();//  加密一次
    }
}

这里subject.login则会调用UserReaml,将用户名和加密后的密码传过去进行验证。如果有错误,比如密码不正确或者用户不存在就给前端返回一个用户名或密码不正确的提示。

登出:

@GetMapping("/logout")
public Result logout() {
    SecurityUtils.getSubject().logout();
   return common.SUCCESS("");
}


3 总结

这里只是简单运用了shiro实现了登录验证。没有去分析源码,有需要的朋友可以自行去官方查阅。

目录
相关文章
|
23小时前
|
缓存 安全 Java
Shiro框架以及Spring Boot整合Shiro
Shiro框架以及Spring Boot整合Shiro
Shiro框架以及Spring Boot整合Shiro
|
23小时前
|
JSON Java Maven
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
45 0
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
|
23小时前
|
安全 算法 Java
SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架
SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架
35 0
|
23小时前
|
开发框架 安全 Java
【Java专题_01】springboot+Shiro+Jwt整合方案
【Java专题_01】springboot+Shiro+Jwt整合方案
|
23小时前
|
Java 关系型数据库 MySQL
Shiro实战+springboot集成
Shiro实战+springboot集成
46 0
|
23小时前
|
前端开发 Java 关系型数据库
【Shiro】Springboot集成Shiro
【Shiro】Springboot集成Shiro
58 1
|
23小时前
|
Java
springboot如何配置使用shiro
【1月更文挑战第11天】springboot如何配置使用shiro
19 2
|
23小时前
|
存储 Java 数据库
SpringBoot+JWT+Shiro
SpringBoot+JWT+Shiro
33 0
|
23小时前
|
存储 JSON 安全
使用shiro对数据库中的密码进行加密存储(java+springboot+shiro)
使用shiro对数据库中的密码进行加密存储(java+springboot+shiro)
103 0
|
23小时前
|
前端开发 Java Spring
使用Spring Boot集成Shiro时出现了无法注入Service的问题
使用Spring Boot集成Shiro时出现了无法注入Service的问题