1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > springboot集成shiro实现用户登录认证

springboot集成shiro实现用户登录认证

时间:2024-06-11 00:27:57

相关推荐

springboot集成shiro实现用户登录认证

Apache Shiro 是一个功能强大且易于使用的Java安全框架,可执行身份验证、授权、加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大的web和企业应用程序。

下面即springboot集成shiro,实现用户登录认证功能

1.原理

shiro外部架构如下:

主要包括三大实体:Subject、Realm、和SecurityManager。

Subject即当前用户,我们可以通过Subject自带的 SecurityUtils.getSubject()方法获取当前对象,并通过当前用户拿到shiro的session,进行后续的认证授权等。

SecurityManager即安全管理器,可以视为拦截器,拦截请求,并转至shiro中处理。

Realm,可以有1个或多个Realm,即安全实体数据源,即用于获取安全实体的;可以是JDBC实现,也可以是LDAP实现,或者内存实现等等;一般由用户自定义实现。

shiro实现过程一般如下,编写shiro配置文件,配置对应的加密方式,并注册进Realm中,然后把对应的realm注入shiro配置中进行注册;编写Realm类,实现对应的登录认证、授权等功能。

2.注入依赖

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

3.编写shiro配置文件

@Configurationpublic class ShiroConfig {//此处用于实现授权功能,配置需要拦截的接口@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);//拦截页面Map<String, String> filterMap = new LinkedHashMap<>();//登录/登出,所有人的权限filterMap.put("/user/login", "anon");filterMap.put("/user/logout", "anon");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);//未登录页面跳转shiroFilterFactoryBean.setLoginUrl("/user/show");//未有权限页面跳转shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauthorized");return shiroFilterFactoryBean;}//注入对应的userRealm类@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager SecurityManager = new DefaultWebSecurityManager();SecurityManager.setRealm(userRealm);return SecurityManager;}@Beanpublic UserRealm userRealm() {UserRealm userRealm = new UserRealm();//注册MD5加密userRealm.setCredentialsMatcher(hashedCredentialsMatcher());return userRealm;}/*** 设置shiro加密方式** @return HashedCredentialsMatcher*/@Beanpublic HashedCredentialsMatcher hashedCredentialsMatcher(){HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();// 使用md5 算法进行加密hashedCredentialsMatcher.setHashAlgorithmName("md5");// 设置散列次数: 意为加密几次hashedCredentialsMatcher.setHashIterations(2);return hashedCredentialsMatcher;}}

4.编写userRealm类,实现登录拦截

@Slf4jpublic class UserRealm extends AuthorizingRealm {@Autowiredprivate UserManageService userManageService;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {/**配置权限*此处User实体需配置属性roles,用户权限*获取当前用户对象* */SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();Subject subject= SecurityUtils.getSubject();UserAccount currentUser =(UserAccount) subject.getPrincipal();authorizationInfo.addStringPermission(currentUser.getRoles());log.info("用户权限为:"+currentUser.getRoles());return authorizationInfo;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;//用户名/密码认证//从接口处获取得到的用户名String username = token.getUsername();//调用mybatis_plus中的方法,查询数据库中用户名对应的数据QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();wrapper.eq("Username",username);UserAccount user=userManageService.getOne(wrapper);//为空,即用户名不存在if(user==null){return null;}else {log.info(user.getUsername());}//principal:认证的实体信息,可以是username,也可以是数据库表对应的用户的实体对象Object principal = user.getUsername();return new SimpleAuthenticationInfo(user, user.getPassword() , ByteSource.Util.bytes(principal),getName());}}

注意:此处进行登录验证时使用了MD5加密,即数据库中存储的密码应是MD5加密后的密文密码,而不是明文密码。

示例如下:

//md5加密admin.setPassword(new Md5Hash(admin.getPassword(), admin.getUsername(),2).toString());

5.编写controller接口

//用户登录(使用用户名)@PostMapping("/login")public CommonResult<Object> UserLogin(@RequestBody UserAccount user){String username=user.getUsername();String password=user.getPassword();//shiro验证Subject subject= SecurityUtils.getSubject();//根据用户名密码生成一个令牌UsernamePasswordToken token=new UsernamePasswordToken(username,password);try {subject.login(token); //执行登录操作} catch (UnknownAccountException e) {log.info("登录用户不存在");return new CommonResult<>(416,"用户不存在",username);} catch (IncorrectCredentialsException e) {log.info("登录密码错误");return new CommonResult<>(412,"密码错误,请重新登录",password);}catch (AuthenticationException e) {log.warn("用户登录异常:" + e.getMessage());return new CommonResult<>(416,"账户异常",username);}return new CommonResult<>(200,"登录成功",username);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。