springboot整合shiro、Md5加密注册

1.首先实现用户注册,在service层实现对明文密码进行md5加密

//用户注册的控制器方法
  @RequestMapping(value="/adduser")
    @ResponseBody
    public Map addUser(HttpServletRequest request) {
        String username=HttpServletRequestUtil.getString(request,"username");
        String password=HttpServletRequestUtil.getString(request,"password");
        TbPersonInfo tbpersonInfo=new TbPersonInfo();
        tbpersonInfo.setName(username);
        tbpersonInfo.setPassword(password);
        int affect=personInfoService.toRegister(tbpersonInfo);
        Map modelmap=new HashMap();
        if(affect>=1){
            modelmap.put("success",true);
        }else {
            modelmap.put("success",false);
        }
        return modelmap;
    }

//业务层实现对明文密码的加密
public Integer toRegister(TbPersonInfo user){
        /**
         * 明文密码进行md5+salt+hash散列
         * Md5Hash md5hash=new Md5Hash(password,""salt",hashIterations:8)
         * */
        String salt= SaltUtil.getSalt(8);
        //注册时,业务层方法需要修改,将随机盐保存到uer对象中,并一同保存到数据库
        String encodedPassword =SaltUtil.shiroPassword(user.getPassword(),salt);
        System.out.println("业务层输出salt"+salt);
        System.out.println("业务层输出password"+encodedPassword);
        user.setSalt(salt);
        user.setPassword(encodedPassword);
        return tbPersonInfoDAO.InsertPersonInfo(user);

    }


/***
     * 对用户的密码进行MD5加密
     * 做成工具类
     */
    public static String shiroPassword(String password,String salt) {

        // shiro 自带的工具类生成salt
        //String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        // 加密次数
        int times = 5;
        // 算法名称
        String algorithmName = "md5";

        String encodedPassword = new SimpleHash(algorithmName,password,salt,times).toString();

        // 返回加密后的密码
        return encodedPassword;
    }



 /**
     * 自定义生成随即盐salt的静态方法
     * */
    public static String getSalt(int n){
        char[] chars="ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789!@#$%^&*()".toCharArray();
         StringBuilder stringBuilder=new StringBuilder();
        //循环,每次取一个随机字符
        for(int i=0;i<n;i++){
            char achar=chars[new Random().nextInt(chars.length)];
            stringBuilder.append(achar);
        }
        return stringBuilder.toString();
    }

2.shiro配置类和自定义Realm

@Configuration
public class ShiroConfig {
         /* *
         * Shiro内置过滤器,可以实现权限相关的拦截器
         *  anon 无需认证(登录)即可以访问
         *  authc:必须认证才可以访问
         *  user :如果使用rememberMe的功能可以直接访问
         *  perms: 该资源必须得到资源权限才可以访问
         *  role  该资源必须得到角色权限才可以访问
         *  layout  注销,直接跳转到登录页面
         * */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManage){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManage);
        
        //设置默认认证界面(一般是登录界面)
        shiroFilterFactoryBean.setLoginUrl("/o2o/login");
        // 设置成功之后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/o2o/tologin");
        // 设置未授权界面,权限认证失败会访问该 URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/o2o/login");


        // LinkedHashMap 是有序的,进行顺序拦截器配置
        Map<String,String> filterChainMap = new LinkedHashMap<>();
        // 配置可以匿名访问的地址,可以根据实际情况自己添加,放行一些静态资源等,anon 表示放行
        filterChainMap.put("/css/**", "anon");
        filterChainMap.put("/imgs/**", "anon");
        filterChainMap.put("/js/**", "anon");
        filterChainMap.put("/swagger-*/**", "anon");
        filterChainMap.put("/swagger-ui.html/**", "anon");
        // 登录 URL 放行
        filterChainMap.put("/o2o/login", "anon");
        //filterChainMap.put("/o2o/**", "authc");
        //配置需要认证的访问地址
        filterChainMap.put("/shop/**", "authc");
        // 配置 logout 过滤器
        filterChainMap.put("/logout", "logout");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return  shiroFilterFactoryBean;
    }

     /**
     * 创建DefaultWebSecurityManager  安全管理器对象
     * */
    @Bean(name="securityManager")
    public DefaultWebSecurityManager 
        getDefaultWebSercurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        //给安全管理器设置realm(读取用户数据)
        securityManager.setRealm(userRealm);
        return  securityManager;

    }
   //获取自定义Realm对象,并修改凭证校验匹配器
    @Bean(name ="userRealm" )
    public UserRealm getRealm(){
        UserRealm realm=new UserRealm();
        HashedCredentialsMatcher hashedCredentialsMatcher = new 
        HashedCredentialsMatcher();
        // 散列算法:这里使用MD5算法;需要和service中设置加密的值一致
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        
        // 散列的次数,比如散列两次,相当于md5(md5(""));,需要和service中设置加密的值一致
        hashedCredentialsMatcher.setHashIterations(5);
        //hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        // 表示是否存储散列后的密码为16进制,需要和生成密码时的一样,默认是base64;
        realm.setCredentialsMatcher(hashedCredentialsMatcher);
        return realm ;
    }








*************************************************************************
public class UserRealm extends AuthorizingRealm {
  //@Resource看到有人用工具类从applicationContext中获取service层的bean,这里其实可以直接注入
    @Autowired
    private TbPersonInfoService tbPersonInfoService;
    //执行授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection 
    principalCollection) {
        return null;
    }


   //执行认证逻辑  用户名校验--密码是上一级(父类中自动去完成)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken 
    authenticationToken) throws AuthenticationException {
    //
        // 根据 Token 获取用户名,如果您不知道该 Token 怎么来的,先可以不管,下文会解释
        String username = (String) authenticationToken.getPrincipal();
        // 根据用户名从数据库中查询该用户
        TbPersonInfo user=tbPersonInfoService.getPasswordByUsername(username);
        String salt=user.getSalt();
        if(user != null) {
            // 把当前用户存到 Session 中
            SecurityUtils.getSubject().getSession().setAttribute("personInfo", user);
            // 传入用户名和密码进行身份认证,并返回认证信息,SimpleAuthenticationInfo构造方法的参数依次为,用户对象(主体),密码名,随机盐,账号名
            AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getName(), user.getPassword(),ByteSource.Util.bytes(salt),getName());
            return authcInfo;
        } else {
            return null;
        }
    }

3.进行登录认证

  //登录校验,控制器方法中获取认证主题和Token,并执行登录认证方法
    @RequestMapping(value="/tologin",method = RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> toLogin(@RequestParam(value="loginName") String name,@RequestParam(value="password")String password,HttpServletRequest request){
        Map<String,Object> modelmap=new HashMap<>();
        // 根据用户名和密码创建 Token
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        // 获取subject认证主体
        Subject subject = SecurityUtils.getSubject();
        try{
            // 开始认证,这一步会跳到我们自定义的 Realm 中
           TbPersonInfo user=personInfoService.getPasswordByUsername(name);
            subject.login(token);
            request.getSession().setAttribute("personInfo", user);
            modelmap.put("personInfo",user);
            modelmap.put("success",true);
        }catch(Exception e){
            modelmap.put("success",false);
        }
        return modelmap;

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值