shrio中hashedCredentialsMatcher密碼匹配示例詳解
類圖如下:
SimpleCredentialsMatcher是明文匹配,也是shrio框架默認(rèn)的比對方式,網(wǎng)上的例子多是此方式。實際項目中,數(shù)據(jù)庫中的密碼一般是密文,此時密碼的匹配需使用HashedCredentialsMatcher完成。
處理過程
在controller中通過Subject的login(token)將接收過來用戶賬號和密碼(明文)交給shrio框架,示例代碼如下
其次通過HashedCredentialsMatcher告訴shrio使用加密方式;
最后通過AuthorizingRealm,將數(shù)據(jù)庫中獲取的密碼,告訴shrio框架,shrio處理完成后返回處理結(jié)果。
示例代碼
數(shù)據(jù)庫創(chuàng)建表user,結(jié)構(gòu)如下:
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `psw` varchar(200) DEFAULT NULL, `user_right` varchar(300) DEFAULT NULL, `create_time` date DEFAULT NULL, `salt` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) )
在dao完成根據(jù)登錄名獲取實體對象和增加用戶兩個方法,略過。service代碼如下,保存代碼時,密碼使用sha256加密,鹽隨機(jī)獲取20位隨機(jī)數(shù)
@Service("UserService") public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService { @Override public UserEntity getUserByname(String loginName) { return baseMapper.queryByUserName(loginName); } @Override public boolean save(UserEntity user) { user.setCreateTime(new Date()); String salt = RandomStringUtils.randomAlphanumeric(20); user.setPsw(new Sha256Hash(user.getPsw(), salt).toHex());//sha256加密 user.setSalt(salt); try { baseMapper.insert(user); return true; } catch (Exception e) { return false; } } }
controller代碼如下
@RestController public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Map<String, Object> login(@RequestParam Map<String, Object> params) { String username=params.get("username").toString(); String password=params.get("password").toString(); String result = "已登錄"; Subject currentUser = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); if (!currentUser.isAuthenticated()) { try { currentUser.login(token);// 會觸發(fā)com.shiro.config.MyShiroRealm的doGetAuthenticationInfo方法 result = "登錄成功"; } catch (UnknownAccountException e) { result = "用戶名錯誤"; } catch (IncorrectCredentialsException e) { e.printStackTrace(); result = "密碼錯誤"; } } return R.ok(result); } @GetMapping("/logout") public void logout() { Subject currentUser = SecurityUtils.getSubject(); UserEntity user = (UserEntity)currentUser.getPrincipal(); System.out.println(user.getName()); currentUser.logout(); } @RequestMapping("/user/add") public String add(@RequestBody UserEntity user) { userService.save(user); System.out.println("新增用戶"); return "hello"; } }
使用ShiroConfig 代替xml配置文件方式
@Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //設(shè)置自定義的securityManager shiroFilterFactoryBean.setSecurityManager(securityManager); //設(shè)置默認(rèn)登錄的url,身份認(rèn)證失敗會訪問該URL shiroFilterFactoryBean.setLoginUrl("/login"); //設(shè)置成功,會訪問該url shiroFilterFactoryBean.setSuccessUrl("/success"); //設(shè)置未授權(quán)界面,權(quán)限認(rèn)證失敗會訪問該url shiroFilterFactoryBean.setUnauthorizedUrl("/notRole"); //進(jìn)行攔截器配置 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // <!-- authc:所有url都必須認(rèn)證通過才可以訪問; anon:所有url都都可以匿名訪問--> filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/front/**", "anon"); filterChainDefinitionMap.put("/user/add", "perms[add]"); filterChainDefinitionMap.put("/admin/**", "authc"); filterChainDefinitionMap.put("/user/**", "authc"); //主要這行代碼必須放在所有權(quán)限設(shè)置的最后,不然會導(dǎo)致所有 url 都被攔截 剩余的都需要認(rèn)證 filterChainDefinitionMap.put("/**", "authc"); //配置logout過濾器 filterChainDefinitionMap.put("/logout","logout"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setRealm(customRealm()); return defaultSecurityManager; } @Bean public CustomRealm customRealm() { CustomRealm customRealm = new CustomRealm(); //SimpleCredentialsMatcher明文匹配,hashedCredentialsMatcher加鹽匹配 customRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return customRealm; } @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("SHA-256"); hashedCredentialsMatcher.setHashIterations(1); return hashedCredentialsMatcher; } }
Realm中代碼如下:
public class CustomRealm extends AuthorizingRealm { @Autowired private UserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //授權(quán)部分代碼略 return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String loginName = (String) authenticationToken.getPrincipal(); UserEntity user= userService.getUserByname(loginName); if (user == null) { // 沒找到帳號 throw new UnknownAccountException(); } // 交給AuthenticatingRealm使用CredentialsMatcher進(jìn)行密碼匹配 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPsw(), ByteSource.Util.bytes(user.getSalt()),getName()); return authenticationInfo; }
測試,使用張三登錄
以上就是shrio中hashedCredentialsMatcher密碼匹配示例詳解的詳細(xì)內(nèi)容,更多關(guān)于shrio中hashedCredentialsMatcher密碼匹配的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
FastJson對于JSON格式字符串、JSON對象及JavaBean之間的相互轉(zhuǎn)換操作
這篇文章主要介紹了FastJson對于JSON格式字符串、JSON對象及JavaBean之間的相互轉(zhuǎn)換,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11SpringBoot使用slf4j日志并輸出到文件中的操作方法
這篇文章主要介紹了SpringBoot使用slf4j日志并輸出到文件中,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08