ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-07-01 10:04:18  阅读:122  来源: 互联网

标签:username return String shiro Springboot new Shiro JavaWeb


1 关于Shiro

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

Subject:指当前的操作用户。

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

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

2 步骤

首先引入Shiro的maven:

<!--整合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是需要登录验证后才能访问。除了这两种还有其他:

authcBasic、logout、noSessionCreation、perms、port、rest、roles、ssl、user。

如果用户开启了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实现了登录验证。没有去分析源码,有需要的朋友可以自行去官方查阅。 

END

编  辑   |   王文星

责  编   |   刘玉江

能力越强,责任越大。实事求是,严谨细致。    

                                                  ——where2go 团队


   

标签:username,return,String,shiro,Springboot,new,Shiro,JavaWeb
来源: https://blog.51cto.com/u_15281984/2962291

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有